dotnet/aspnetcore · error · Error

Incomplete message.

Error message

Incomplete message.

What it means

Thrown when the declared message size (decoded from the prefix) exceeds the remaining bytes in the input ArrayBuffer — i.e. the prefix says N more bytes follow, but only fewer are present. Standard SignalR partial-frame condition: the parser received the length header but not the full body.

Solutions

  1. Buffer incoming bytes until at least (prefixLength + declaredSize) bytes are available before calling parse.
  2. If using the official signalr client and you see this, report it as a transport bug — the client should reassemble for you.
  3. On a real disconnect, propagate the error and reconnect with a fresh HubConnection.

Example fix

// before
const msgs = BinaryMessageFormat.parse(buffer); // partial body present

// after — accumulate until the declared size is fully present
const prefix = readVarint(buffer);
if (buffer.byteLength < prefix.bytes + prefix.size) {
  return { needMore: true };
}
const msgs = BinaryMessageFormat.parse(buffer);
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check that the declared body is fully present
function hasFullBody(buf: Uint8Array, offset: number, maxLen: number): boolean {
  let size = 0, numBytes = 0, byteRead;
  do {
    byteRead = buf[offset + numBytes];
    size |= (byteRead & 0x7f) << (7 * numBytes);
    numBytes++;
  } while (numBytes < maxLen && (byteRead & 0x80) !== 0);
  return buf.byteLength >= offset + numBytes + size;
}

Type guard

function isCompleteFrame(buf: Uint8Array, offset: number): boolean {
  // returns true only when prefix + declared body fit in buf
  // (use hasFullBody implementation)
  return hasFullBody(buf, offset, 5);
}

Try / catch

try { return BinaryMessageFormat.parse(buf); }
catch (e) {
  if (/Incomplete message/.test((e as Error).message)) {
    pendingBuffer = concat(pendingBuffer, buf); return []; // wait for more
  }
  throw e;
}

Prevention

When it happens

Trigger: Feeding BinaryMessageFormat.parse a buffer that contains a complete prefix but a truncated body. Common in custom transports that do not wait for the full frame, or when the WebSocket emitted a partial message and the caller did not buffer across reads.

Common situations: Custom transport integration that calls parse per chunk instead of accumulating; the official client expects the transport layer (WebSocket.onmessage) to deliver complete frames so end-users usually see this only when intercepting the stream; server disconnected mid-write.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/19eebd352650aeff. Report an issue: GitHub.

Appendix: source

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

                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 3600ca084e)