dotnet/aspnetcore · critical
Cannot read message size.
Error message
Cannot read message size.
What it means
Thrown by BinaryMessageFormat.parse while reading the VarInt length prefix. The parser reads up to maxLengthPrefixSize (5) bytes, each contributing 7 bits, stopping when the continuation bit (0x80) is clear. If after consuming all available bytes the continuation bit is still set AND fewer than 5 bytes were read, the prefix is truncated and the size cannot be determined.
Source
Thrown at src/SignalR/clients/ts/signalr-protocol-msgpack/src/BinaryMessageFormat.ts:50
public static parse(input: ArrayBuffer): Uint8Array[] {
const result: Uint8Array[] = [];
const uint8Array = new Uint8Array(input);
const maxLengthPrefixSize = 5;
const numBitsToShift = [0, 7, 14, 21, 28 ];
for (let offset = 0; offset < input.byteLength;) {
let numBytes = 0;
let size = 0;
let byteRead;
do {
byteRead = uint8Array[offset + numBytes];
size = size | ((byteRead & 0x7f) << (numBitsToShift[numBytes]));
numBytes++;
}
while (numBytes < Math.min(maxLengthPrefixSize, input.byteLength - offset) && (byteRead & 0x80) !== 0);
if ((byteRead & 0x80) !== 0 && numBytes < maxLengthPrefixSize) {
throw new Error("Cannot read message size.");
}
if (numBytes === maxLengthPrefixSize && byteRead > 7) {
throw new Error("Messages bigger than 2GB are not supported.");
}
if (uint8Array.byteLength >= (offset + numBytes + size)) {
// IE does not support .slice() so use subarray
result.push(uint8Array.slice
? uint8Array.slice(offset + numBytes, offset + numBytes + size)
: uint8Array.subarray(offset + numBytes, offset + numBytes + size));
} else {
throw new Error("Incomplete message.");
}
offset = offset + numBytes + size;
}
View on GitHub (pinned to 294cab2f9b)
Solutions
- Confirm the SignalR client and server run compatible MessagePack protocol versions.
- Check intermediary proxies for frame size limits and timeouts.
- Capture the raw bytes at both ends to detect truncation/corruption.
- Reconnect on a fresh transport; transient corruption usually resolves on reconnect.
Example fix
// before
// hub connection reusing a corrupted buffer after a transient drop
// after
connection.onclose(async (e) => { if (shouldReconnect(e)) await connection.start(); });
// and ensure proxy max frame size > your largest payload Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
try { await connection.start(); } catch (e) { if (/Cannot read message size/i.test(e.message)) { await reconnectWithBackoff(); } else throw e; } Prevention
- Match SignalR client and server MessagePack versions.
- Check proxy frame-size/timeout settings.
- Reconnect on a fresh transport when framing corruption appears.
When it happens
Trigger: A truncated/corrupt MessagePack frame whose length prefix was cut off mid-VarInt; a fragmented socket read delivered only part of the header; a misbehaving proxy truncating frames; bytes from a different protocol mixed into the stream. In a correct SignalR MsgPack transport this indicates wire corruption or a framing bug.
Common situations: Reverse proxy/load balancer truncating large frames; a bug in a custom transport; buffer slicing that drops bytes; version skew between MessagePack hub protocol implementations; network interruption mid-frame.
Related errors
- Messages bigger than 2GB are not supported.
- Incomplete message.
- MessagePack message was length %d but claimed to be length %
- The length header was incomplete
- Error reading length header.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/5195da7c59f67488.
Report an issue: GitHub.