I’m trying to start/stop an external canister that my Orbit station controls, but I can’t find a way to do this through either the Orbit Wallet UI or dfx-orbit CLI.
Failed to execute command: Error in the IC agent: The replica returned a rejection error:
reject code CanisterError, reject message Error from Canister g24fd-zaaaa-aaaac-qc2pq-cai:
Canister called `ic0.trap` with message: 'Unauthorized access to resources:
ExternalCanister(Call(CallExternalCanister(NoValidationMethod,
ExecutionMethod(CanisterMethod(aaaaa-aa,stop_canister)))))'.
3. Adding IC Management Canister as External Canister
I tried adding aaaaa-aa as an external canister in the Orbit UI to configure permissions, but the UI validation rejects it with “This field must be a valid canister id.”
4. Adding myself as co-controller via IC Settings (workaround)
As a workaround, I tried adding my dfx principal as a co-controller through IC Settings in the Orbit UI. I added the principal, clicked Save, and approved the request, but the controller change doesn’t appear to take effect. Running dfx canister --network ic info still shows only the Orbit station as controller.
Questions
Is there a built-in way to start/stop canisters in Orbit? (UI or CLI)
Let me first respond to your question regarding the Orbit GUI:
Orbit GUI abstracts away some of the low-level ICP concepts that most users don’t need to understand to successfully operate canisters using Orbit. In particular, stopping and starting a canister are low-level operations most often needed in the context of canister upgrades.
For reference, a canister lifecycle usually looks like this:
create canister
install code (for the first time)
start canister
the canister runs for some time
stop the canister
install code (mode = upgrade)
start canister
repeat from step 4
And the same sequence from the perspective of the Orbit GUI:
ADD CANISTER
INSTALL
the canister runs for some time
UPGRADE
repeat from step 3
Why would a user need to stop a canister? One valid use case is to avoid draining cycles when the canister is not needed anymore. However, most of the time it is sufficient to take one of the following actions:
Most of the runtime costs of a canister that no one is using will probably come from work that it does in the background via timers. Anticipate that the canister is not going to be used all the time, and program it to cancel of of its timers (a.k.a. periodic tasks) when there is no more demand (also, avoid using the legacy heartbeats feature since it cannot be canceled).
If the canister will not be useful ever again, it should be deleted, not just stopped. This isn’t supported via the Orbit GUI yet.
Let obsolete canisters run out of cycles. If you set up cycles monitoring, you should be able to keep your canister’s cycles balance between, e.g., 5T and 10T cycles, which would make if safe to operate. If you decide in the future that this canister isn’t needed anymore, you could just let it run out of cycles, in which case you would waste just 10 XDR in the worst case.
To summarize, stopping a canister is usually a means to an end. And the best approach depends on your use case.
Orbit is designed to manage canister call requests for canisters that it controls. The management canister is a different thing, it actually isn’t a canister at all (better to think of it as a low-level API for talking to one of the subnets) and thus it is not an Orbit-controlled canister, so wiring calls to the management canister via Orbit won’t work.
This approach is indeed a workaround, as it reduced the usefulness of Orbit. But it should work. If it doesn’t, you should still see the details of the request in the Orbit Wallet view. For example:
Thank you @aterga for your detailed answer. I now have a clearer view of the sequence on Orbit GUI.
I understand that Orbit GUI abstracts away low-level ICP concepts, but shouldn’t users still be able to trigger stop/start from dfx-orbit CLI?
Also, consider this scenario: A user without deep code knowledge relies on Orbit GUI to abstract these concepts. They push an upgrade containing a critical bug, and the canister is now actively causing damage (draining cycles, corrupting state, etc.) –> it needs to be stopped immediately.
Currently, there’s no path to do this:
GUI has no stop/start option
Delete isn’t supported yet either, and even if it were, you’d lose the canister ID permanently, breaking any canisters or frontends that depend on it. The user don’t want this solution either.
The only workaround I can think of is uploading a dummy WASM (that might requires the approval workflow → not ideal for emergencies).
In case an upgrade of an Orbit-controlled canister contains a critical bug that has been discovered in production, an administrator can respond by installing a different Wasm module, e.g.:
Roll forward (preferred) — Patch the bug, build a new Wasm, and use the INSTALL feature with mode = Upgrade.
Roll back — If (1) there’s no time to create a patched Wasm, (2) this is not the first Wasm version ever used for this canister, and (3) if the canister data is safe, then the previous Wasm can be installed again, also using INSTALL feature with mode = Upgrade.
Stopgap — If a canister snapshot hasn’t been taken recently, take a snapshot; then, install any other safe Wasm module using the INSTALL feature with mode = Reinstall.
In practice, rolling forward is almost always the best approach. Note that the patched Wasm could be a temporary workaround (a.k.a. hotfix); a proper solution could be rolled out later.
Cycle draining could be mitigate as I described:
It’s worth adding that canisters can have a configurable freezing threshold that determines the cycle balance at which they automatically freeze (without a freezing threshold, a canister would be deleted if its cycles balance dropped to zero). A frozen canister can be un-frozen simply by topping it up (no risk of data loss, just service interruption).
I don’t think manually stopping the canister would help prevent data corruption. Instead, data corruption could be mitigated via canister snapshots. It is recommended to take a snapshot right before an upgrade, especially if the upgrade contains a data migration (since a bug in the latter could corrupt data). Note that only one snapshot is currently supported in the Orbit GUI. But I think even that is enough for most users (let me know if you disagree).