{"record":{"id":"82acfcce644f980c","repo":"linera-io/linera-protocol","slug":"failed-to-deserialize-message","errorCode":null,"errorMessage":"Failed to deserialize message","messagePattern":"Failed to deserialize message","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"linera-sdk/src/contract/mod.rs","lineNumber":81,"sourceCode":"                        let operation = <$contract as $crate::abi::ContractAbi>::deserialize_operation(operation)\n                            .expect(\"Failed to deserialize `Operation` in execute_operation\");\n\n                        let response = contract.execute_operation(operation).blocking_wait();\n\n                        <$contract as $crate::abi::ContractAbi>::serialize_response(response)\n                            .expect(\"Failed to serialize `Response` in execute_operation\")\n                    },\n                )\n            }\n\n            fn execute_message(message: Vec<u8>) {\n                use $crate::util::BlockingWait as _;\n                $crate::contract::run_async_entrypoint::<$contract, _, _>(\n                    unsafe { &mut CONTRACT },\n                    move |contract| {\n                        let message: <$contract as $crate::Contract>::Message =\n                            $crate::bcs::from_bytes(&message)\n                                .expect(\"Failed to deserialize message\");\n\n                        contract.execute_message(message).blocking_wait()\n                    },\n                )\n            }\n\n            fn process_streams(updates: Vec<\n                $crate::contract::wit::exports::linera::app::contract_entrypoints::StreamUpdate,\n            >) {\n                use $crate::util::BlockingWait as _;\n                $crate::contract::run_async_entrypoint::<$contract, _, _>(\n                    unsafe { &mut CONTRACT },\n                    move |contract| {\n                        let updates = updates.into_iter().map(Into::into).collect();\n                        contract.process_streams(updates).blocking_wait()\n                    },\n                )\n            }","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-sdk/src/contract/mod.rs#L63-L99","documentation":"The contract macro's execute_message entrypoint (linera-sdk/src/contract/mod.rs) BCS-deserializes incoming message bytes into the contract's Message type and expects success. The panic fires when a cross-application/cross-chain message was serialized from a different Message schema than this contract declares - e.g. the sending application was upgraded but the receiving contract was not. The panic aborts message execution in the receiving contract.","triggerScenarios":"A message arrives from an application instance whose Message type differs from the receiving contract's: sender upgraded with changed message variants while the receiver runs old bytecode, or an application ID reused across incompatible versions.","commonSituations":"Inter-application messaging between two versions of the same dApp; a frontend composing messages with stale shared types; partial redeployment where only the sender was upgraded.","solutions":["Redeploy both sender and receiver from the same shared crate so Message types match exactly.","Treat any type change to Message as a new application version: publish anew rather than reusing the ID.","Pin dApp component versions in the manifest so all modules deploy together.","Round-trip test messages (bcs::to_bytes/from_bytes) in CI to catch schema drift before deploy."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before sending a message to another application, verify both sides share the ABI:\nuse counter_app_abi::Message; // shared crate compiled into both applications\nlet bytes = bcs::to_bytes(&message)?;\nbcs::from_bytes::<Message>(&bytes)?; // schema sanity check off-chain","typeGuard":"fn message_round_trips(msg: &Message) -> bool {\n    bcs::to_bytes(msg).ok().and_then(|b| bcs::from_bytes::<Message>(&b).ok()).is_some()\n}","tryCatchPattern":"// Deserialization happens inside the receiving contract's runtime; a panic fails the\n// message execution on-chain and is not catchable by the sender. Prevent by validating\n// ABI compatibility before dispatch (bytecode hash + shared crate version check).","preventionTips":["Keep Message in the shared crate and depend on it from both sender and receiver.","Upgrade communicating applications together in one deployment, never piecemeal.","Pin application module versions in the manifest and verify bytecode hashes after publish."],"tags":["linera-sdk","contract","bcs","message","abi-mismatch","deserialization","panic","rust"],"backgroundTag":"abi-version-mismatch","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}