{"record":{"id":"468a038e6c1aa921","repo":"dotnet/aspnetcore","slug":"expected-a-handshake-response-from-the-server","errorCode":null,"errorMessage":"Expected a handshake response from the server.","messagePattern":"Expected a handshake response from the server\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/SignalR/clients/ts/signalr/src/HandshakeProtocol.ts","lineNumber":61,"sourceCode":"        } else {\n            const textData: string = data;\n            const separatorIndex = textData.indexOf(TextMessageFormat.RecordSeparator);\n            if (separatorIndex === -1) {\n                throw new Error(\"Message is incomplete.\");\n            }\n\n            // content before separator is handshake response\n            // optional content after is additional messages\n            const responseLength = separatorIndex + 1;\n            messageData = textData.substring(0, responseLength);\n            remainingData = (textData.length > responseLength) ? textData.substring(responseLength) : null;\n        }\n\n        // At this point we should have just the single handshake message\n        const messages = TextMessageFormat.parse(messageData);\n        const response = JSON.parse(messages[0]);\n        if (response.type) {\n            throw new Error(\"Expected a handshake response from the server.\");\n        }\n        const responseMessage: HandshakeResponseMessage = response;\n\n        // multiple messages could have arrived with handshake\n        // return additional data to be parsed as usual, or null if all parsed\n        return [remainingData, responseMessage];\n    }\n}\n","sourceCodeStart":43,"sourceCodeEnd":70,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/SignalR/clients/ts/signalr/src/HandshakeProtocol.ts#L43-L70","documentation":"After parsing the handshake frame, HandshakeProtocol checks whether the decoded JSON has a top-level 'type' field. A genuine handshake response has no type (it carries error/minorVersion/userId), so presence of type means the server sent a regular HubMessage instead of the expected handshake response — a protocol-level mismatch.","triggerScenarios":"parseHandshakeResponse decodes a JSON object that has a 'type' property. Happens when the server speaks an incompatible protocol version that puts an error in a typed message, when the client connected mid-stream and received a hub message first, or when the handshake response was malformed by a proxy.","commonSituations":"Client/server protocol version mismatch (e.g. an older server that emits a typed handshake error). Connecting to a hub that is mid-broadcast. A man-in-the-middle or debug proxy that re-frames messages.","solutions":["Match client and server SignalR versions (same major).","If the server sends a handshake error, capture it server-side via its logs and resolve the underlying configuration.","Retry the connection; a transient mid-stream condition can clear.","Verify no proxy is reordering or re-framing the message stream."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function isHandshakeResponse(obj: unknown): boolean {\n  return typeof obj === \"object\" && obj !== null && !(\"type\" in obj);\n}","typeGuard":"function isHandshakeResponseMessage(v: unknown): v is { error?: string } {\n  return typeof v === \"object\" && v !== null && !(\"type\" in v);\n}","tryCatchPattern":"try { await connection.start(); }\ncatch (e) {\n  if (e instanceof Error && e.message.includes(\"Expected a handshake response\")) {\n    console.error(\"Protocol mismatch: client/server SignalR versions differ.\");\n  }\n  throw e;\n}","preventionTips":["Keep client and server SignalR majors aligned.","Do not let a proxy reorder or re-frame the stream.","Re-run the handshake on this error via withAutomaticReconnect()."],"tags":["handshake","protocol","version-mismatch"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}