clockworklabs/SpacetimeDB · error

Procedure return value failed to serialize to BSATN

Error message

Procedure return value failed to serialize to BSATN

What it means

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.

Source

Thrown at crates/core/src/host/module_host.rs:2782

        }

        let ProcedureResultTarget { sender, request_id } = target;
        let CallProcedureReturn { result, tx_offset } = ret;
        match sender.config.version {
            WsVersion::V1 => {
                let message = ProcedureResultMessage::from_result(&result, request_id);
                self.subscriptions().send_procedure_message(sender, message, tx_offset)
            }
            WsVersion::V2 | WsVersion::V3 => {
                let (status, timestamp, execution_duration) = match result {
                    Ok(ProcedureCallResult {
                        return_val,
                        execution_duration,
                        start_timestamp,
                    }) => (
                        ws_v2::ProcedureStatus::Returned(
                            bsatn::to_vec(&return_val)
                                .expect("Procedure return value failed to serialize to BSATN")
                                .into(),
                        ),
                        start_timestamp,
                        TimeDuration::from(execution_duration),
                    ),
                    Err(err) => (
                        ws_v2::ProcedureStatus::InternalError(err.to_string().into()),
                        Timestamp::UNIX_EPOCH,
                        TimeDuration::ZERO,
                    ),
                };

                let message = ws_v2::ProcedureResult {
                    status,
                    timestamp,
                    total_host_execution_duration: execution_duration,
                    request_id,
                };

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Republish the module and regenerate client bindings so type definitions match.
  2. Add a module-side unit test asserting `bsatn::to_vec(&sample_return)` succeeds.
  3. Use derived SpacetimeType impls; never hand-write Serialize for procedure returns.
  4. Pin consistent spacetimedb crate/SDK versions.

Example fix

// before: custom Serialize on the return value risks a host panic
impl Serialize for MyRet { fn serialize(...) { ... custom error path ... } }

// after: derive and verify encodability
#[derive(spacetimedb::SpacetimeType, Clone)]
pub struct MyRet { pub items: Vec<Item> }

#[test]
fn ret_encodes() { assert!(spacetimedb_lib::bsatn::to_vec(&MyRet::sample()).is_ok()); }
Defensive patterns

Strategy: type-guard

Validate before calling

// Before publishing, assert the return type encodes under BSATN
#[test]
fn returns_bsatn_encode() { assert!(spacetimedb_lib::bsatn::to_vec(&MyRet::sample()).is_ok()); }

Type guard

fn assert_bsatn_serializable<T: spacetimedb_lib::bsatn::Serialize>() {}

Prevention

When it happens

Trigger: 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.

Common situations: Module return types changed while old clients stay connected; custom Serialize on return values; SDK/macro version skew producing invalid types.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/316710b34d84bb9f. Report an issue: GitHub.