{"record":{"id":"316710b34d84bb9f","repo":"clockworklabs/SpacetimeDB","slug":"procedure-return-value-failed-to-serialize-to-bsat-316710","errorCode":null,"errorMessage":"Procedure return value failed to serialize to BSATN","messagePattern":"Procedure return value failed to serialize to BSATN","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/core/src/host/module_host.rs","lineNumber":2782,"sourceCode":"        }\n\n        let ProcedureResultTarget { sender, request_id } = target;\n        let CallProcedureReturn { result, tx_offset } = ret;\n        match sender.config.version {\n            WsVersion::V1 => {\n                let message = ProcedureResultMessage::from_result(&result, request_id);\n                self.subscriptions().send_procedure_message(sender, message, tx_offset)\n            }\n            WsVersion::V2 | WsVersion::V3 => {\n                let (status, timestamp, execution_duration) = match result {\n                    Ok(ProcedureCallResult {\n                        return_val,\n                        execution_duration,\n                        start_timestamp,\n                    }) => (\n                        ws_v2::ProcedureStatus::Returned(\n                            bsatn::to_vec(&return_val)\n                                .expect(\"Procedure return value failed to serialize to BSATN\")\n                                .into(),\n                        ),\n                        start_timestamp,\n                        TimeDuration::from(execution_duration),\n                    ),\n                    Err(err) => (\n                        ws_v2::ProcedureStatus::InternalError(err.to_string().into()),\n                        Timestamp::UNIX_EPOCH,\n                        TimeDuration::ZERO,\n                    ),\n                };\n\n                let message = ws_v2::ProcedureResult {\n                    status,\n                    timestamp,\n                    total_host_execution_duration: execution_duration,\n                    request_id,\n                };","sourceCodeStart":2764,"sourceCodeEnd":2800,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/core/src/host/module_host.rs#L2764-L2800","documentation":"On WebSocket protocol v2/v3, the module host serializes a successful procedure's return value with `bsatn::to_vec(&return_val).expect(\"Procedure return value failed to serialize to BSATN\")` to build a ProcedureStatus::Returned message. BSATN encoding of a well-formed SpacetimeType is effectively infallible, so this panic signals a malformed return type: a custom Serialize that errors or schema/runtime type drift after changing the module.","triggerScenarios":"A procedure call succeeding on WS v2/v3 whose return value then fails BSATN encoding — hand-written Serialize impls returning errors, or a module republished/edited without regenerating client bindings so runtime type and schema disagree.","commonSituations":"Module return types changed while old clients stay connected; custom Serialize on return values; SDK/macro version skew producing invalid types.","solutions":["Republish the module and regenerate client bindings so type definitions match.","Add a module-side unit test asserting `bsatn::to_vec(&sample_return)` succeeds.","Use derived SpacetimeType impls; never hand-write Serialize for procedure returns.","Pin consistent spacetimedb crate/SDK versions."],"exampleFix":"// before: custom Serialize on the return value risks a host panic\nimpl Serialize for MyRet { fn serialize(...) { ... custom error path ... } }\n\n// after: derive and verify encodability\n#[derive(spacetimedb::SpacetimeType, Clone)]\npub struct MyRet { pub items: Vec<Item> }\n\n#[test]\nfn ret_encodes() { assert!(spacetimedb_lib::bsatn::to_vec(&MyRet::sample()).is_ok()); }","handlingStrategy":"type-guard","validationCode":"// Before publishing, assert the return type encodes under BSATN\n#[test]\nfn returns_bsatn_encode() { assert!(spacetimedb_lib::bsatn::to_vec(&MyRet::sample()).is_ok()); }","typeGuard":"fn assert_bsatn_serializable<T: spacetimedb_lib::bsatn::Serialize>() {}","tryCatchPattern":null,"preventionTips":["Republish modules and regenerate bindings whenever return types change.","Never hand-write Serialize for values crossing the WS v2/v3 boundary.","Keep module and SDK versions aligned."],"tags":["rust","spacetimedb","bsatn","serialization","procedure","websocket-v2"],"backgroundTag":"bsatn-serialization-failed","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}