{"record":{"id":"de47748cbb25e673","repo":"clockworklabs/SpacetimeDB","slug":"unrecognised-extra-bytes-in-the-description","errorCode":null,"errorMessage":"Unrecognised extra bytes in the {description}","messagePattern":"Unrecognised extra bytes in the (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"crates/bindings-csharp/Runtime/Internal/Module.cs","lineNumber":618,"sourceCode":"\n    public static IViewContext CreateViewContext(\n        ulong sender_0,\n        ulong sender_1,\n        ulong sender_2,\n        ulong sender_3\n    )\n    {\n        var sender = Identity.From(MemoryMarshal.AsBytes([sender_0, sender_1, sender_2, sender_3]));\n        return newViewContext!(sender);\n    }\n\n    public static IAnonymousViewContext CreateAnonymousViewContext() => newAnonymousViewContext!();\n\n    public static void EnsureNoUnreadBytes(MemoryStream stream, string description)\n    {\n        if (stream.Position != stream.Length)\n        {\n            throw new Exception($\"Unrecognised extra bytes in the {description}\");\n        }\n    }\n\n    public static Errno WriteReducerError(BytesSink error, Exception e)\n    {\n        var error_str = e.Message ?? e.GetType().FullName ?? e.GetType().Name;\n        var error_bytes = System.Text.Encoding.UTF8.GetBytes(error_str);\n        error.Write(error_bytes);\n        return Errno.HOST_CALL_FAILURE;\n    }\n\n    private static void Write(this BytesSink sink, ReadOnlySpan<byte> bytes)\n    {\n        while (!bytes.IsEmpty)\n        {\n            var written = bytes.Length;\n            FFI.bytes_sink_write(sink, bytes, ref written);\n            bytes = bytes[written..];","sourceCodeStart":600,"sourceCodeEnd":636,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/3653d2ed498fddbd83b7062aa6bf8970e18635ec/crates/bindings-csharp/Runtime/Internal/Module.cs#L600-L636","documentation":"After decoding a BSATN-encoded payload into an anonymous view context, SpacetimeDB checks that the MemoryStream was fully consumed via EnsureNoUnreadBytes. Leftover bytes mean the encoded data contains more fields than the decoder knew how to read — usually a schema mismatch between writer and reader. The library throws because silently ignoring trailing bytes could hide data loss or corruption.","triggerScenarios":"Calling a code path that ends in Module.EnsureNoUnreadBytes(stream, description) (e.g. anonymous view/context deserialization) with a buffer whose byte length exceeds what the expected type's BSATN decoder reads — decoding an older/newer struct version, wrong type, or corrupted/padded payload.","commonSituations":"Client and server module compiled from different schema versions (field added on the writer side); decoding bytes with the wrong expected type; manually concatenated or truncated BSATN buffers; stale generated bindings after a module update.","solutions":["Regenerate C# bindings and redeploy the module so writer and reader share the same schema version","Verify you are decoding with the correct expected type for the payload","Inspect the raw bytes: remove padding, truncation, or accidental concatenation of multiple payloads","If the extra field is intentional on the writer side, add it to the reader type or use a forward-compatible decoding path"],"exampleFix":"// before\nvar ctx = Module.CreateAnonymousViewContext();\nctx.Decode(oldBytes); // throws: Unrecognised extra bytes\n// after\nvar ctx = Module.CreateAnonymousViewContext();\nctx.Decode(bytesProducedByCurrentSchema); // writer & reader schemas match","handlingStrategy":"try-catch","validationCode":"// before decoding, sanity-check that the buffer is fully consumable by the expected type\nvar expected = Bsatn.SizeOf<MyPayloadType>(bytes);\nif (bytes.Length != expected)\n    throw new InvalidOperationException(\n        $\"Payload length {bytes.Length} != expected schema size {expected}\");","typeGuard":"static bool IsFullyConsumable(MemoryStream s) => s.Position == s.Length;","tryCatchPattern":"try\n{\n    var ctx = DecodeAnonymousViewContext(stream);\n}\ncatch (Exception ex) when (ex.Message.StartsWith(\"Unrecognised extra bytes\"))\n{\n    logger.LogError(ex, \"BSATN schema mismatch: reader consumed fewer bytes than payload contains\");\n    throw new SchemaMismatchException(ex.Message, ex);\n}","preventionTips":["Regenerate C# bindings whenever the server module schema changes","Pin writer and reader to the same module version / schema hash","Never hand-build or pad BSATN buffers; use the generated encoder","Add a round-trip test: encode with the writer, decode with the reader, assert no leftover bytes"],"tags":["csharp","spacetimedb","bsatn","deserialization","schema-mismatch"],"backgroundTag":"schema-validation-failed","analyzedSha":"3653d2ed498fddbd83b7062aa6bf8970e18635ec","analyzedAt":"2026-09-06T02:33:02.036Z","contentChangedAt":"2026-09-06T02:33:02.036Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}