I try to migrate a new non optional field in my heap memory using Serde but, I get following error:
Request ID: 2e0dc0659e5c1c445882d82deadd0df89c18a0f074b24b5b5d533852aa011fea
Reject code: 5
Reject text: Canister xo2hm-lqaaa-aaaal-ab3oa-cai trapped explicitly: Panicked at 'called `Result::unwrap()` on an `Err` value: "Custom(Fail to decode argument 0\n\nCaused by:\n Subtyping error: field memory is not optional field)"', src/satellite/src/lib.rs:104:50
at m_ (file:///opt/homebrew/lib/node_modules/@junobuild/cli/dist/index.js:42:2120)
i.e. field memory is not optional field
My struct look like:
#[derive(CandidType, Serialize, Deserialize, Clone, Debug)]
pub struct Rule {
#[serde(default)]
pub memory: Memory,
}
#[derive(CandidType, Serialize, Deserialize, Clone, Debug)]
pub enum Memory {
Heap,
Stable,
}
And I got an implementation
impl Default for Memory {
fn default() -> Self { Memory::Heap }
}
What am I missing?
You need serde(default) for Memory too I believe.
Try this :
#[derive(CandidType, Serialize, Deserialize, Default, Clone, Debug)]
pub enum Memory {
#[default]
Heap,
Stable,
}
also try deriving Default for Rule.
#[derive(CandidType, Serialize, Deserialize, Default, Clone, Debug)]
pub struct Rule {
#[serde(default)]
pub memory: Memory,
}
1 Like
Thanks, did not thought about it. Unfortunately though, same same.
#[derive(CandidType, Serialize, Deserialize, Default, Clone, Debug)]
pub struct Rule {
#[serde(default)]
pub memory: Memory,
}
// Deleted my implementation
#[derive(CandidType, Serialize, Deserialize, Default, Clone, Debug)]
pub enum Memory {
#[default]
Heap,
Stable,
}
Also tried to bump last version of Serde, just in case.
Is this a backward compatibility issue? Have you tried reinstalling the canister?
Otherwise you can do Option<Memory> as a measure to allow backward compatibility but itâs probably not needed this early on.
I try to upgrade existing canister without reinstalling those - preserving the state.
I can set the memory as Option<Memory> but, because itâs a really important information, I was hoping to be able to introduce it as a non optional value. Just feel wrong to have it optional but, indeed if no other option, I ultimately have to, agree with you.
If you want to preserve the state then yeah youâd have to introduce optional types.
Or what weâre doing is ensuring that every single type has a valid default (even if itâs something like Unspecified which wonât pass a validation check.)
That way you can change the schema, and when you deserialize into the type it
a) skips values that exist in the serialized data that donât exist in the new type
b) sets a default for values that donât exist in the data but are new to the type.
As long as your types have Serialize/Deserialize and Default this should work. We havenât really tested it a lot though.
1 Like
I had to fix some stuffs in a FE project so, when I finally went back to mine I decided to accept my fate and set those new variable as Option<Memory>.
Upgrade worked like a charm and now there is the first Junoâs smart contract on mainnet that supports stable memory.
Thanks a lot for the help!
2 Likes
No problems. When weâve done more testing on our ORM Iâll be happy to share it to see if it helps.
2 Likes