{"record":{"id":"ab20c94b5cc4d3b4","repo":"clockworklabs/SpacetimeDB","slug":"error-while-reading-typeof-t-fullname-expected","errorCode":null,"errorMessage":"Error while reading {typeof(T).FullName}: expected source span to be {expectedSize} bytes long, but was {source.Length} bytes.","messagePattern":"Error while reading (.+?): expected source span to be (.+?) bytes long, but was (.+?) bytes\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"crates/bindings-csharp/BSATN.Runtime/Builtins.cs","lineNumber":61,"sourceCode":"#endif\n    }\n\n    /// <summary>\n    /// Convert the passed byte array to a value of type T, optionally reversing it before performing the conversion.\n    /// If the input is not reversed, it is treated as having the native endianness of the host system.\n    /// (The endianness of the host system can be checked via System.BitConverter.IsLittleEndian.)\n    /// </summary>\n    /// <typeparam name=\"T\"></typeparam>\n    /// <param name=\"source\"></param>\n    /// <param name=\"littleEndian\"></param>\n    /// <returns></returns>\n    public static T Read<T>(ReadOnlySpan<byte> source, bool littleEndian)\n        where T : struct\n    {\n        var expectedSize = Marshal.SizeOf<T>();\n        if (source.Length != expectedSize)\n        {\n            throw new ArgumentException(\n                $\"Error while reading {typeof(T).FullName}: expected source span to be {expectedSize} bytes long, but was {source.Length} bytes.\"\n            );\n        }\n\n        var result = MemoryMarshal.Read<T>(source);\n\n        if (littleEndian != BitConverter.IsLittleEndian)\n        {\n            AsBytes(ref result).Reverse();\n        }\n\n        return result;\n    }\n\n    /// <summary>\n    /// Convert a hex string to a byte array.\n    /// </summary>\n    /// <param name=\"hex\"></param>","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-csharp/BSATN.Runtime/Builtins.cs#L43-L79","documentation":"Util.Read<T>(source, littleEndian) deserializes a blittable struct straight from a byte span via MemoryMarshal and therefore requires the span to be exactly Marshal.SizeOf<T>() bytes (16 for ConnectionId, 32 for Identity). A length mismatch means the byte sequence cannot possibly be that struct, so it fails fast with ArgumentException instead of reading garbage.","triggerScenarios":"Calling ConnectionId.FromBigEndian/Identity.FromBigEndian (both delegate to Util.Read) with a byte array that is too short or too long: hex decoded from a wrong-length string, a truncated network/DB blob, or a buffer with extra trailing bytes.","commonSituations":"Decoding hex strings without length validation; slicing bugs (wrong offset/length) when carving values out of a larger buffer; schema drift where the stored value size changed between versions.","solutions":["Check bytes.Length == Marshal.SizeOf<T>() (16 / 32 for the ID types) before calling","Prefer the FromHexString entry points, which validate the hex length up front with a clearer message","Fix slicing arithmetic: verify offset + size <= buffer.Length and that you advance by the element size","Log the actual length on failure to pinpoint which producer emits the wrong size"],"exampleFix":"// before\nvar id = ConnectionId.FromBigEndian(Util.StringToByteArray(hex)); // may throw later with generic message\n\n// after\nif (hex.Length != 32) throw new ArgumentException($\"Expected 32 hex chars, got {hex.Length}\");\nvar id = ConnectionId.FromHexString(hex);","handlingStrategy":"validation","validationCode":"static ConnectionId ReadConnectionId(byte[] bytes)\n{\n    if (bytes.Length != 16)\n        throw new ArgumentException($\"ConnectionId payload must be 16 bytes, got {bytes.Length}\");\n    return ConnectionId.FromBigEndian(bytes);\n}","typeGuard":null,"tryCatchPattern":"try { id = Util.Read<ConnectionId>(span, littleEndian: false); }\ncatch (ArgumentException ex) { logger.LogError(\"Bad ID payload: {Message}\", ex.Message); throw; }","preventionTips":["Validate byte-array lengths against the expected struct size before FromBigEndian/Util.Read","Prefer FromHexString entry points which give clearer length errors","Unit-test buffer slicing helpers with boundary lengths (0, size-1, size, size+1)"],"tags":["csharp","bsatn","deserialization","buffer-length","spacetimedb"],"backgroundTag":"buffer-length-mismatch","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}