Suppose we have:
let v = {
c: Int;
};
Can the canister with this be upgraded to
let v = {
var c: Int;
};
without losing c
state?
Suppose we have:
let v = {
c: Int;
};
Can the canister with this be upgraded to
let v = {
var c: Int;
};
without losing c
state?
This only becomes an issue once you have stable
variables. If we have
stable let foo = {
count = 0
};
then when upgrading we’ll get a warning of
Incompatible stable signature will cause data loss:
stable variable foo of previous type
{count : Nat}
cannot be consumed at new type
{var count : Nat}
and data will be lost.
So, how can we fix this? We can migrate our data to a new structure, either in a post_upgrade
hook, using a helper function, or by using an upgrade method. Since going from count
to var count
is simple, let’s do a helper function.
stable let foo = {
count = 0;
};
private func migrate_foo () : {var count: Nat} {
return {
var count = foo.count;
}
};
stable let foo_v2 = migrate_foo();
We can keep the original foo, and then set foo_v2
equal to the result of our migrate_foo
function during initialization. This will transform the previous type into our new type, and set a new variable.
After the data and our public methods are upgraded to use foo_v2
, we can safely delete our stable foo
variable in a future upgrade.
Here’s some example code: Motoko Playground