dotnet/aspnetcore · error

Messages bigger than 2GB are not supported.

Error message

Messages bigger than 2GB are not supported.

What it means

Thrown by BinaryMessageFormat.parse when the length prefix is a full 5 bytes long (the maximum) and the 5th byte is greater than 7. The VarInt decoding uses 7 bits per byte; 5 bytes give 35 bits, but JS bitwise ops are 32-bit and the design caps at 2^32, so a 5th byte > 7 would imply a payload larger than ~2GB, which the runtime explicitly refuses.

Source

Thrown at src/SignalR/clients/ts/signalr-protocol-msgpack/src/BinaryMessageFormat.ts:54

        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;
        }

        return result;
    }
}

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Cap and validate message sizes server-side (configure maximum receive message size on the SignalR hub).
  2. Stream large payloads instead of single frames (IAsyncEnumerable / streaming).
  3. If untrusted, treat this as a protocol violation and terminate the connection.
  4. Verify you are not pointing a MsgPack parser at a JSON or text stream.

Example fix

// before
// single SendAsync with a multi-GB payload
await connection.InvokeAsync("Process", hugeBuffer);

// after
// stream in chunks
await foreach (var chunk in connection.StreamAsync<Chunk>("ProcessStream", hugeBuffer)) { /* ... */ }
Defensive patterns

Strategy: validation

Validate before calling

function validateMaxSize(prefixBytes) {
  if (prefixBytes.length === 5 && prefixBytes[4] > 7) throw new Error('Frame too large; configure server max message size or stream the data.');
}

Type guard

null

Try / catch

try { await connection.invoke('Process', payload); } catch (e) { if (/bigger than 2GB/i.test(e.message)) { /* switch to streaming */ } else throw e; }

Prevention

When it happens

Trigger: A legitimately enormous MessagePack frame (>2GB), or (far more commonly) a corrupt/attacker-controlled prefix whose high bytes are set. SignalR MsgPack frames in practice should be far smaller; hitting this usually means the prefix bytes are garbage rather than a real payload size.

Common situations: Memory corruption in the transport; a malicious peer crafting oversized prefixes; a serialization bug producing absurd sizes; misinterpreting a non-MsgPack stream as MsgPack.

Related errors


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