dotnet/aspnetcore · error · RuntimeException

The length header was incomplete

Error message

The length header was incomplete

What it means

readLengthHeader reads the varint prefix byte-by-byte; if the buffer runs out of bytes before a terminating varint byte (MSB clear) is reached, the header is incomplete and the message cannot be framed.

Source

Thrown at src/SignalR/clients/java/signalr/messagepack/src/main/java/com/microsoft/signalr/messagepack/Utils.java:37

        // VarInt: 0x35 - %00110101 - the most significant bit is 0 so the value is %x0110101 i.e. 0x35 (53)
        // VarInt: 0x80 0x25 - %10000000 %00101001 - the most significant bit of the first byte is 1 so the
        // remaining bits (%x0000000) are the lowest bits of the value. The most significant bit of the second
        // byte is 0 meaning this is last byte of the VarInt. The actual value bits (%x0101001) need to be
        // prepended to the bits we already read so the values is %01010010000000 i.e. 0x1480 (5248)
        // We support payloads up to 2GB so the biggest number we support is 7fffffff which when encoded as
        // VarInt is 0xFF 0xFF 0xFF 0xFF 0x07 - hence the maximum length prefix is 5 bytes.
        
        int length = 0;
        int numBytes = 0;
        int maxLength = 5;
        byte curr;
        
        do {
            // If we run out of bytes before we finish reading the length header, the message is malformed
            if (buffer.hasRemaining()) {
                curr = buffer.get();
            } else {
                throw new RuntimeException("The length header was incomplete");
            }
            length = length | (curr & (byte) 0x7f) << (numBytes * 7);
            numBytes++;
        } while (numBytes < maxLength && (curr & (byte) 0x80) != 0);
        
        // Max header length is 5, and the maximum value of the 5th byte is 0x07
        if ((curr & (byte) 0x80) != 0 || (numBytes == maxLength && curr > (byte) 0x07)) {
            throw new RuntimeException("Messages over 2GB in size are not supported");
        }
        
        return length;
    }
    
    public static ArrayList<Byte> getLengthHeader(int length) {
        // This code writes length prefix of the message as a VarInt. Read the comment in
        // the readLengthHeader for details.
        
        ArrayList<Byte> header = new ArrayList<Byte>();

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Ensure the transport reassembles complete frames before handing them to the protocol.
  2. Verify the peer is not sending partial frames.
  3. Check for framing/offset bugs if you layer a custom transport.
Defensive patterns

Strategy: try-catch

Try / catch

// Java
try {
    hubConnection.start().blockingAwait();
} catch (RuntimeException ex) {
    if (ex.getMessage() != null && ex.getMessage().contains("length header was incomplete")) {
    }
}

Prevention

When it happens

Trigger: Buffer ends mid-varint; a payload containing only a partial length prefix; transport delivers a fragment rather than a complete frame.

Common situations: Truncated transport read; incorrect frame reassembly; connection drop mid-frame; proxy splitting the stream.

Related errors


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