dotnet/aspnetcore · error · Error
Cannot read message size.
Error message
Cannot read message size.
What it means
Thrown by BinaryMessageFormat.parse during SignalR MessagePack framing when the varint length prefix cannot be fully read. The parser reads up to maxLengthPrefixSize bytes of a 7-bit-prefixed length; if the high bit (0x80) is still set after exhausting the input buffer without reaching maxLengthPrefixSize, the prefix is truncated and unreadable.
Solutions
- Confirm the SignalR server is sending complete frames (the server's MessageHubProtocol is the canonical source).
- Inspect the raw bytes at the failing offset — a length prefix whose continuation bits never terminate indicates truncation.
- If using a custom transport, ensure buffers accumulate until a complete frame is available before invoking parse.
- Treat this as a connection-level failure: close and re-establish the SignalR connection rather than retrying the parse.
Example fix
// before
const messages = BinaryMessageFormat.parse(partialBuffer);
// after — accumulate chunks until a full frame is available
function appendAndParse(acc, chunk) {
const buf = concat(acc, chunk);
try { return { consumed: ..., messages: BinaryMessageFormat.parse(buf) }; }
catch (e) {
if (/Cannot read message size/.test(e.message)) return { consumed: 0, messages: [], pending: buf };
throw e;
}
} Defensive patterns
Strategy: retry
Validate before calling
// Pre-check: do we even have enough bytes for a length prefix?
function canReadLengthPrefix(buf: Uint8Array, offset: number, maxLen: number): boolean {
for (let i = 0; i < maxLen; i++) {
if (offset + i >= buf.byteLength) return false;
if ((buf[offset + i] & 0x80) === 0) return true; // final byte of prefix
}
return true;
} Type guard
function isCompleteLengthPrefix(buf: Uint8Array, offset: number, maxLen: number): boolean {
for (let i = 0; offset + i < buf.byteLength && i < maxLen; i++) {
if ((buf[offset + i] & 0x80) === 0) return true;
}
return false;
} Try / catch
try {
const messages = BinaryMessageFormat.parse(buffer);
} catch (e) {
if (/Cannot read message size/.test((e as Error).message)) {
// accumulate more bytes; the prefix was truncated
pendingBuffer = concat(pendingBuffer, buffer);
return;
}
throw e;
} Prevention
- Buffer incoming bytes until a complete length prefix is present before parsing.
- Use the official transport layer (which reassembles frames) instead of parsing raw chunks.
- Treat unparseable frames as a connection-level failure.
When it happens
Trigger: A MessagePack SignalR message arrives whose length-prefix bytes span the boundary of a partial read and the remaining bytes never arrive; a malformed/manually-crafted frame whose length prefix has all high bits set; a transport that delivered a slice mid-frame and the connection closed before more data arrived.
Common situations: Intermittent network drop mid-message over WebSockets; a proxy/CDN that fragments frames; corrupt wire data from a non-conforming server; feeding a hand-buffered (truncated) ArrayBuffer into the parser during testing.
Related errors
- Incomplete message.
- Invalid payload.
- MessagePack message was length
- Messages over 2GB in size are not supported
- The length header was incomplete
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/5195da7c59f67488.
Report an issue: GitHub.
Appendix: 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 3600ca084e)