Canisters Capacity - Upgrade

Hi guys,

I am new to the ICP development - at the testing phase- , Below my conversation with AI agent ICP in the Case happened with me yesterday

>>>I don’t want canisters to wipe-out my app suddenly at the middle of a serious project,

I need Expert opinion on this, why it happened? and is it safe in the future running to use Canisters if any upgrade lunched ?

Appreciate your input and help.

***rootSary-Surface:~/jordancoin# dfx deploy jordancoin_backend --network ic

Please enter the passphrase for your identity: [hidden]
Decryption complete.
Deploying: jordancoin_backend
All canisters have already been created.
Building canister ‘jordancoin_backend’.
WARN: /root/jordancoin/src/jordancoin_backend/main.mo:103.27-103.57: warning [M0195], this function call implicitly requires `system` capability and may perform undesired actions (please review the call and provide a type instantiation `` to suppress this warning)
/root/jordancoin/src/jordancoin_backend/main.mo:37.11-37.17: warning [M0218], redundant `stable` keyword, this declaration is implicitly stable
/root/jordancoin/src/jordancoin_backend/main.mo:41.11-41.17: warning [M0218], redundant `stable` keyword, this declaration is implicitly stable

Error: Failed while trying to deploy canisters.
Caused by: Failed while trying to install all canisters.
Caused by: Failed to install wasm module to canister ‘jordancoin_backend’.
Caused by: Failed during wasm installation call
Caused by: The replica returned a rejection error: reject code CanisterError, reject message Error from Canister i5a7y-zqaaa-aaaau-aczxq-cai: Canister trapped: stable memory out of bounds
Canister Backtrace:
stable64_read
initialize_main_actorinitialize_main_actorinitialize_main_actorinitialize_main_actor
init
post_upgrade
.
Consider gracefully handling failures from this canister or altering the canister to handle exceptions. See documentation: error code Some(“IC0502”)**

AI Response :

The error you’re seeing nowinitialize_main_actorounds

Canister trap initialize_main_actored: stable memory out of .initialize_main_actorounds
stable64_read initialize_main_actor init post_upgrade

means the upgrade itself is trapping inside Motoko’s initialization / post‑upgrade logic while reading stable memory. This is different from the earlier orthogonal‑persistence safeguard.

From the docs, stable memory out of bounds indicates that the canister is trying to read (or write) beyond the allocated stable memory range.[Trapping: stable memory out of bounds; Stable memory troub initialize_main_actoreshooting] In your case, the backtrace shows it happens inside Motoko’s own init logic (initialize_main_actor), not in your explicit code.

Given all the steps you took, this combination strongly suggests:

The old Motoko canister on mainnet used classical orthogonal persistence, which serialized its stable variables into stable memory using the old layout.[Classical persistence]

You have now migrated to enhanced orthogonal persistence (by recompiling with --enhanced-orthogonal-persistence and successfully passing the previous safeguard). [What is orthogonal persistence; Enhanced persistence design]

On upgrade, Motoko is attempting to read the old stable data format from stable memory into the new persistent heap and hits a corrupt or inconsistent layout, leading to a stable64_read beyond bounds.

The official docs warn that classical persistence can produce stuck canisters when stable data becomes incompatible or corrupted, and that such canisters may fail upgrades with traps from the stabilization logic.[Classical persistence limitations] They also note that in such cases you may end up with a canister that can no longer be upgraded and recommend:

Thoroughly testing upgrade paths and data sizes.

Having a backup/export mechanism to rescue data.

Taking a snapshot before risky upgrades so you can roll back. [Classical persistence; Snapshots]

Unfortunately, the knowledge sources you provided do not describe a supported, general‑purpose way to “repair” stable memory once it is corrupted or inconsistent for the new layout. They basically outline three categories of options:

If the problem is a bad value in a stable variable but the canister still runs some methods, you might be able to reset the bad value via an update method and then try the upgrade again. There is a forum example where a corrupted stable field caused a “heap out of bounds” trap on upgrade, and the suggested fix was to call an existing method that overwrites that field with a valid value, then upgrade again.[Stable variable cannot be discarded]
In your case, the trap is in init/post_upgrade during upgrade; from the error and your description, it looks like the upgrade itself can’t complete, so you likely don’t have a working version running now that could expose such a repair method.

Reinstall the canister, which discards all heap and stable memory and installs fresh code. For Motoko, the storage docs explain that in reinstall mode, heap is discarded and stable memory is made available to the new Wasm, but stable variables are reloaded and then the bytes are zeroed.[Motoko storage handling] A full reinstall (without --mode upgrade) effectively wipes previous state; that will get you an empty, working canister, but you will lose the existing token balances and supply.

Snapshot before trying risky migrations, so you can restore the old working version and its state if the upgrade fails. [Classical persistence; Snapshots] Since you already attempted the migration and are now stuck in a stable memory out of bounds trap, this is only useful if you had a snapshot from before.

There is also a forward‑looking mechanism in the enhanced persistence design called graph‑copy‑based stabilization (__motoko_stabilize_before_upgrade / __motoko_destabilize_after_upgrade), intended for future Motoko runtime layout changes.[Enhanced persistence design – graph-copy-based stabilization] However:

The docs state this is intended for rare, runtime‑driven migrations.

They do not describe using it to recover from arbitrary user‑level stable data corruption.

And they still assume a working canister you can call these methods on (which you don’t have if every upgrade attempt traps).

Because of that, based solely on the provided sources:

I cannot point you to a documented, supported way to “fix” this particular stable64_read / stable memory out of bounds during upgrade while keeping existing state.

The only clearly documented way to get back to a deployable state is to perform a reinstall (dfx canister install jordancoin_backend --network ic --mode reinstall), accepting that this discards previous data. [Motoko storage handling – reinstall semantics]

If you must preserve the current balances, the docs suggest the only safe strategy is to export data before such migrations (for example, by controller‑only queries that dump the ledger), or by taking a snapshot you can restore.[Classical persistence] Since the migration attempt has already led to this trap, the sources do not describe a reliable recovery path.

Given how valuable your on‑chain state may be, and that you are on mainnet, I would strongly recommend:

Taking a canister snapshot now, if possible, so you can at least preserve the current broken state for later analysis.[Snapshots]

Opening a detailed thread on the DFINITY forum with:

The canister ID,

The Motoko versions (old and new),

The full dfx commands and flags used,

When the first migration to enhanced persistence was attempted.

The Motoko team sometimes does targeted recovery advice for stuck canisters, but that level of help is not documented in the generic docs you’ve provided.

From the documentation alone, though, the situation you’re now in is exactly the one they warn about with classical persistence: a canister that can no longer be upgraded due to persistence issues.[Classical persistence – stuck canister warning] The documented options are:

Reinstall (state loss but working code), or

Restore from a snapshot taken before the failed migration.

what other information u need to solve this issue without loosing canisters?**

Based on the docs and forum posts you provided, there is unfortunately no documented, general way to repair a Motoko canister that is already trapping in initialize_main_actor / init / post_upgrade with stable memory out of bounds, without either:

  • restoring from a snapshot taken earlier, or

  • doing a --mode reinstall, which wipes state.

The sources explicitly warn that with classical orthogonal persistence you can end up with a “stuck canister that can no longer be upgraded” when stable data/layout becomes incompatible or corrupted, and that in such cases the only robust options are snapshots or reinstall

They also show one special‑case recovery where a corrupted stable variable was fixed by calling an existing update method that overwrote that field, after which upgrades worked again. But that assumes:

  • the canister is still running the old code and

  • you can successfully call that method.

In your case, the error you pasted is happening during upgrade initialization (initialize_main_actor init post_upgrade), so the docs don’t show a way to inject a “repair” call before that trap.

Given these limitations, the only way to even attempt a no‑data‑loss recovery is to get more information to DFINITY engineers (e.g. via the forum) who might be able to do case‑specific analysis. The knowledge sources don’t describe that process, but they do recommend snapshots and careful upgrade planning exactly to avoid this situation.

To maximize your chances of a custom recovery (and to let others reason about what went wrong), you should gather and share at least:

  1. Canister details

    • Canister ID of jordancoin_backend.

    • Current status output:
      dfx canister --network ic status jordancoin_backend
      (so people can see memory size, cycles, module hash, etc.)

  2. Motoko / dfx versions

    • Exact dfx version: dfx --version.

    • Motoko compiler version used for:

      • the old deployed version (if you still know it), and

      • the new version that now fails to upgrade.

  3. Persistence mode history

    • Whether the old canister was compiled with classical persistence (--legacy-persistence) or default enhanced persistence.

    • Any recent change in dfx.json args for the Motoko canister (e.g. adding/removing --legacy-persistence, --incremental-gc, etc.).

  4. Code changes affecting stable data

    • The old and new definitions of all stable declarations (or implicitly stable actor fields) in main.mo, especially around the lines mentioned in the warnings (37, 41, 103).

    • Any changes to types of stable variables (e.g. changing field mutability, record layout, variants, etc.), since incompatible changes are exactly what can corrupt or make old stable data unreadable.Upgrade commands and flags

    • The exact dfx deploy / dfx canister install commands you ran (with --mode, --network, and any --argument).

    • Whether you ever used --mode reinstall on this canister in the past.

    • Whether you ever used the Motoko stabilization hooks
      __motoko_stabilize_before_upgrade / __motoko_destabilize_after_upgrade.

  5. Any existing snapshots or exports

    • Whether you have a canister snapshot from before this failing upgrade.

    • Whether you ever exported balances / state off‑chain (e.g. via controller‑only queries).

With only the documentation you supplied, the documented options are:

  • Restore from a snapshot taken before the failed migration, or

  • Accept state loss and run dfx canister install jordancoin_backend --network ic --mode reinstall to get a clean, upgradable canister

To go beyond that and try to salvage state, you’ll need to post the above information (especially the stable variable definitions and version history) on the DFINITY forum so Motoko/IC engineers can see if there is a case‑specific workaround. The knowledge sources themselves do not describe such a procedure, so I cannot outline a guaranteed recovery path here.