clockworklabs/SpacetimeDB · error

Failed to BSATN-deserialize `{}`: {err:#?}

Error message

Failed to BSATN-deserialize `{}`: {err:#?}

What it means

read_bytes_source_as drains a BytesSource (scheduled-reducer arguments, HTTP body bytes, etc.) into a buffer and BSATN-decodes it as T, panicking with T's type name and the debug error when decoding fails. A decode failure means the bytes were not produced by the schema T expects - a producer/consumer schema mismatch, not corrupted memory.

Source

Thrown at crates/bindings/src/rt.rs:1429

    _reducer: R,
    args: A,
) {
    let arg_bytes = bsatn::to_vec(&SerDeArgs(args)).unwrap();

    // Schedule the reducer.
    sys::volatile_nonatomic_schedule_immediate(R2::NAME, &arg_bytes)
}

/// Read `source` completely into a temporary buffer, then BSATN-deserialize it as a `T`.
///
/// Panics if the bytes from `source` fail to deserialize as `T`.
/// The type name of `T` will be included in the panic message.
#[cfg_attr(not(feature = "unstable"), allow(unused))]
pub(crate) fn read_bytes_source_as<T: DeserializeOwned + 'static>(source: BytesSource) -> T {
    let mut buf = IterBuf::take();
    read_bytes_source_into(source, &mut buf);
    bsatn::from_slice::<T>(&buf)
        .unwrap_or_else(|err| panic!("Failed to BSATN-deserialize `{}`: {err:#?}", std::any::type_name::<T>()))
}

pub trait ExplicitNames {
    fn explicit_names() -> RawExplicitNames {
        RawExplicitNames::default()
    }
}

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Make the reader's type identical to the writer's type and rebuild/redeploy both together.
  2. If a scheduled reducer's args type changed, clear or migrate outstanding scheduled rows before invoking the new code.
  3. Regenerate client bindings so request/response types match the module's current schema.

Example fix

// before: scheduled args type changed, old rows still decode as the old shape
#[spacetimedb::scheduled(reducer = tick)]
pub struct Tick { pub retries: u32 }

// after: keep scheduled row layouts compatible or clear stale rows before deploying
spacetime call my-db delete_all_scheduled_tick  // or migrate in `init`/migration reducer
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Reading a scheduled reducer's stored argument rows after the module schema changed (old rows encode the old row type); decoding an HTTP request body as a type that does not match what the client serialized; module crate version differing between the writer and reader of the bytes.

Common situations: Redeploying a module that changed a scheduled reducer's argument type while scheduled rows persisted in the database; client and module disagreeing on the request body type after a partial upgrade.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/8b8a380c7883e67d. Report an issue: GitHub.