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

  1. Confirm the SignalR client and server run compatible MessagePack protocol versions.
  2. Check intermediary proxies for frame size limits and timeouts.
  3. Capture the raw bytes at both ends to detect truncation/corruption.
  4. 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

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


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/5195da7c59f67488. Report an issue: GitHub.