Wrong magic number post_upgrade Rust

This is the first time I have attempted to do an upgrade and preserve state in Rust. I can’t even get a simple vector to persist. Here’s some simplified code:

async fn pre_upgrade() {
    let numbers: Vec<i32> = vec![1, 2, 3];
    ic_cdk::storage::stable_save((numbers,)).expect("this should work");

async fn post_upgrade() {
    let (numbers,): (Vec<i32>,) = ic_cdk::storage::stable_restore().expect("this should work");

When I deploy I keep getting the following errors. I’ve tried a combination of different values and I always get the same error:

Panicked at 'this should work: "Custom(\"wrong magic number [0, 0, 0, 0]\")"', canisters/graphql/src/graphql.rs:38:80


Does it work if you make the functions non-async?

I just tried and that has no effect. I’ve also noticed that my pre_upgrade function does not seem to be called (it is not logging), so perhaps post_upgrade is looking for a value that doesn’t exist. I’ll keep digging.

Which dfx command do you use to start the upgrade?

I’m getting strange intermittent behavior, not sure what’s going on. I’ve got it working now, but not sure what made it work. I’m using dfx deploy canister-name.

Actually, it might be working as intended, I might just be confused by the fact that the pre_upgrade and post_upgrade won’t run as written until the deployment after they are part of the binary. Am I thinking of this correctly?

I have no more issues with the example, even with async functions. I was probably confused by not deploying enough times to see the effects.

Ah, right, when you upgraded from the old version V1 that didn’t have upgrade hooks to the new version V2 that had them, (non-existing) pre_upgrade was called on V1 and post_upgrade was called on V2, which caused post_upgrade to fail because it wasn’t ready to handle empty stable memory.


Yeah it can be fun getting your head around this when making changes can’t it!

For others reading this thread—there’s a bit of time-travel thinking involved in this: changes to post_upgrade will execute when you deploy them, changes to pre_upgrade will execute on the deploy /after/ that one.