dotnet/aspnetcore · error · Error
Message is incomplete.
Error message
Message is incomplete.
What it means
While parsing a binary handshake response, HandshakeProtocol looks for the RecordSeparator byte (0x1E) in the incoming Uint8Array. If indexOf returns -1, the buffer does not contain a complete handshake frame, so the message is incomplete and cannot be parsed.
Solutions
- Confirm the endpoint is an ASP.NET Core SignalR hub speaking the binary protocol.
- If you are buffering manually, ensure you accumulate bytes until the 0x1E separator arrives before calling parseHandshakeResponse.
- Retry the connection; transient fragmentation often resolves on reconnect.
- Inspect the raw incoming bytes (log message content) to verify the separator is missing vs. the data being garbage.
Defensive patterns
Strategy: retry
Validate before calling
function hasRecordSeparator(bytes: Uint8Array): boolean {
return bytes.indexOf(0x1e) !== -1;
}
// accumulate until separator present before handing off to the protocol Type guard
function isCompleteBinaryHandshake(bytes: Uint8Array): boolean {
return bytes.indexOf(0x1e) !== -1;
} Try / catch
import { HandshakeProtocol } from "@microsoft/signalr";
async function startWithRetry(conn: signalR.HubConnection, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try { await conn.start(); return; }
catch (e) {
if (e instanceof Error && e.message === "Message is incomplete." && i < attempts - 1) {
await new Promise(r => setTimeout(r, 500 * (i + 1)));
continue;
}
throw e;
}
}
} Prevention
- Enable automatic reconnects (.withAutomaticReconnect()) so transient fragmentation self-heals.
- If buffering manually, accumulate bytes until 0x1E arrives.
- Confirm the endpoint speaks the binary SignalR protocol.
When it happens
Trigger: parseHandshakeResponse receives an ArrayBuffer that lacks the 0x1E terminator. Happens when the transport delivered a partial frame (TCP fragmentation mid-handshake), when a binary protocol is fed a non-SignalR payload, or when the underlying transport's onreceive callback hands off an incomplete chunk.
Common situations: Slow or lossy network where the first chunk of the handshake arrives split. A proxy buffering or re-chunking the response. Mismatch between client transport expectation (binary) and what the server actually sent (text). Connecting to a non-SignalR binary endpoint.
Related errors
- Binary protocols over XmlHttpRequest not implementing…
- Expected data to be of type
- Message is incomplete.
- Message is incomplete.
- Authentication refresh is only supported with HTTP-based…
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/4594a02506260070.
Report an issue: GitHub.
Appendix: source
Thrown at src/SignalR/clients/ts/signalr/src/HandshakeProtocol.ts:35
}
/** @private */
export class HandshakeProtocol {
// Handshake request is always JSON
public writeHandshakeRequest(handshakeRequest: HandshakeRequestMessage): string {
return TextMessageFormat.write(JSON.stringify(handshakeRequest));
}
public parseHandshakeResponse(data: any): [any, HandshakeResponseMessage] {
let messageData: string;
let remainingData: any;
if (isArrayBuffer(data)) {
// Format is binary but still need to read JSON text from handshake response
const binaryData = new Uint8Array(data);
const separatorIndex = binaryData.indexOf(TextMessageFormat.RecordSeparatorCode);
if (separatorIndex === -1) {
throw new Error("Message is incomplete.");
}
// content before separator is handshake response
// optional content after is additional messages
const responseLength = separatorIndex + 1;
messageData = String.fromCharCode.apply(null, Array.prototype.slice.call(binaryData.slice(0, responseLength)));
remainingData = (binaryData.byteLength > responseLength) ? binaryData.slice(responseLength).buffer : null;
} else {
const textData: string = data;
const separatorIndex = textData.indexOf(TextMessageFormat.RecordSeparator);
if (separatorIndex === -1) {
throw new Error("Message is incomplete.");
}
// content before separator is handshake response
// optional content after is additional messages
const responseLength = separatorIndex + 1;
messageData = textData.substring(0, responseLength);View on GitHub (pinned to 3600ca084e)