{"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/6dee26c6efc2856793e12b148a59742964f5d783/crates/bindings-csharp/BSATN.Runtime/Builtins.cs#L43-L79","documentation":"Util.Read<T> deserializes a blittable struct T directly over a ReadOnlySpan<byte> using MemoryMarshal.Read, which requires the span to be exactly Marshal.SizeOf<T>() bytes. A shorter or longer span throws ArgumentException naming the expected size (16 for ConnectionId, 32 for Identity).","triggerScenarios":"Calling ConnectionId.FromBigEndian/Identity.FromBigEndian (which delegate to Util.Read) with a span of the wrong length: hex decoded to the wrong byte count, a truncated payload, or a slice with the wrong end offset.","commonSituations":"Converting ids from hex or binary without validating width; interop with systems emitting different fixed-width ids; off-by-one slicing in parsers.","solutions":["Length-check the span against the expected width (16 for ConnectionId, 32 for Identity) before calling FromBigEndian","Fix the upstream producer so it emits exactly the right byte width","Prefer FromHexString, which validates the character count first with a clearer error"],"exampleFix":"// before\nvar id = Identity.FromBigEndian(Util.StringToByteArray(userInput)); // 20 bytes -> ArgumentException\n\n// after\nvar id = Identity.FromHexString(userInput); // validates 64 hex chars first, clearer failure","handlingStrategy":"validation","validationCode":"static bool IsConnectionIdBytes(ReadOnlySpan<byte> b) => b.Length == 16;\nstatic bool IsIdentityBytes(ReadOnlySpan<byte> b) => b.Length == 32;","typeGuard":null,"tryCatchPattern":"try\n{\n    id = Identity.FromBigEndian(source);\n}\ncatch (ArgumentException ex)\n{\n    throw new FormatException($\"Unexpected id width: {ex.Message}\", ex);\n}","preventionTips":["Validate byte width before FromBigEndian calls","Prefer FromHexString entry points for user-supplied input","Verify slicing math when carving ids out of larger buffers"],"tags":["csharp","spacetimedb","bsatn","interop","bytemanipulation"],"backgroundTag":"byte-array-length-mismatch","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}