clockworklabs/SpacetimeDB · error · ArgumentException
Error while reading {typeof(T).FullName}: expected source sp
Error message
Error while reading {typeof(T).FullName}: expected source span to be {expectedSize} bytes long, but was {source.Length} bytes. What it means
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.
Source
Thrown at crates/bindings-csharp/BSATN.Runtime/Builtins.cs:61
#endif
}
/// <summary>
/// Convert the passed byte array to a value of type T, optionally reversing it before performing the conversion.
/// If the input is not reversed, it is treated as having the native endianness of the host system.
/// (The endianness of the host system can be checked via System.BitConverter.IsLittleEndian.)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="littleEndian"></param>
/// <returns></returns>
public static T Read<T>(ReadOnlySpan<byte> source, bool littleEndian)
where T : struct
{
var expectedSize = Marshal.SizeOf<T>();
if (source.Length != expectedSize)
{
throw new ArgumentException(
$"Error while reading {typeof(T).FullName}: expected source span to be {expectedSize} bytes long, but was {source.Length} bytes."
);
}
var result = MemoryMarshal.Read<T>(source);
if (littleEndian != BitConverter.IsLittleEndian)
{
AsBytes(ref result).Reverse();
}
return result;
}
/// <summary>
/// Convert a hex string to a byte array.
/// </summary>
/// <param name="hex"></param>View on GitHub (pinned to 524b4487d9)
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
Example fix
// before
var id = ConnectionId.FromBigEndian(Util.StringToByteArray(hex)); // may throw later with generic message
// after
if (hex.Length != 32) throw new ArgumentException($"Expected 32 hex chars, got {hex.Length}");
var id = ConnectionId.FromHexString(hex); Defensive patterns
Strategy: validation
Validate before calling
static ConnectionId ReadConnectionId(byte[] bytes)
{
if (bytes.Length != 16)
throw new ArgumentException($"ConnectionId payload must be 16 bytes, got {bytes.Length}");
return ConnectionId.FromBigEndian(bytes);
} Try / catch
try { id = Util.Read<ConnectionId>(span, littleEndian: false); }
catch (ArgumentException ex) { logger.LogError("Bad ID payload: {Message}", ex.Message); throw; } Prevention
- 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)
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Unrecognized extra bytes while decoding BSATN value
- cannot deserialize refs without a typespace
- Tried to read ${n} byte(s) at relative offset ${this.offset}
- never types are not yet supported in C# output
- Unsupported --dotnet-version {version}. Supported values: 8,
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/ab20c94b5cc4d3b4.
Report an issue: GitHub.