{"record":{"id":"166f122a172c23cd","repo":"microsoft/garnet","slug":"unexpected-response-response","errorCode":null,"errorMessage":"Unexpected response: {response}]","messagePattern":"Unexpected response: (.+?)\\]","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"libs/client/ClientSession/GarnetClientSession.cs","lineNumber":666,"sourceCode":"                        case (byte)'-':\n                            error = true;\n                            if (!RespReadResponseUtils.TryReadErrorAsString(out result, ref ptr, recvBufferPtr + bytesRead))\n                                success = false;\n                            break;\n\n                        case (byte)'$':\n                            if (!RespReadResponseUtils.TryReadStringWithLengthHeader(out result, ref ptr, recvBufferPtr + bytesRead))\n                                success = false;\n                            break;\n\n                        case (byte)'*':\n                            isArray = true;\n                            if (!RespReadResponseUtils.TryReadStringArrayWithLengthHeader(out resultArray, ref ptr, recvBufferPtr + bytesRead))\n                                success = false;\n                            break;\n\n                        default:\n                            throw new Exception(\"Unexpected response: \" + Encoding.UTF8.GetString(new Span<byte>(recvBufferPtr, bytesRead)).Replace(\"\\n\", \"|\").Replace(\"\\r\", \"\") + \"]\");\n                    }\n                }\n\n                if (!success) return readHead;\n                readHead = (int)(ptr - recvBufferPtr);\n\n                Interlocked.Decrement(ref numCommands);\n                if (isArray)\n                {\n                    var tcs = tcsArrayQueue.Dequeue();\n                    tcs?.SetResult(resultArray);\n                }\n                else if (!RawResult)\n                {\n                    var tcs = tcsQueue.Dequeue();\n                    if (error) tcs?.SetException(new Exception(result));\n                    else tcs?.SetResult(result);\n                }","sourceCodeStart":648,"sourceCodeEnd":684,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/client/ClientSession/GarnetClientSession.cs#L648-L684","documentation":"ProcessReplies switches on the first byte of each RESP reply (+, :, -, $, *) and throws for any other leading byte, dumping the raw received bytes (with newlines turned to '|') into the message. This is a protocol-violation guard: the server sent a reply that is not a recognized RESP type, indicating corruption, a partial frame, an unexpected server-side message, or a version/protocol mismatch. The trailing ']' in the message is a literal formatting artifact.","triggerScenarios":"The GarnetClientSession receives bytes that do not begin with a valid RESP type marker — e.g. a RESP3-only reply when the client speaks RESP2, a truncated/misaligned buffer due to a framing bug, an authentication/SSL renegotiation injected into the data stream, or garbage from connecting to a non-Garnet/non-Redis service.","commonSituations":"Connecting the GarnetClientSession to a non-RESP server on the same port; a TLS/plain-text mismatch (plaintext bytes parsed as RESP); server version emitting a reply type the client parser does not handle; buffer offset desync after a prior partial read.","solutions":["Verify the endpoint is actually a Garnet/Redis-compatible RESP server.","Ensure TLS settings match between client and server (do not send plaintext to a TLS port or vice-versa).","Capture the logged raw bytes to identify the unexpected server message — often reveals an AUTH error or wrong-protocol reply.","Check for protocol version mismatches (RESP2 vs RESP3) and align client/server versions."],"exampleFix":"// before — client not enabling TLS against a TLS-only server\nvar session = new GarnetClientSession(endpoint, sslOptions: null, ...);\n\n// after — match the server's transport security\nvar session = new GarnetClientSession(endpoint,\n    sslOptions: new SslClientAuthenticationOptions { TargetHost = host }, ...);","handlingStrategy":"try-catch","validationCode":"// Ensure the endpoint speaks RESP and TLS settings match before relying on replies\n// (no in-band pre-check; capture raw bytes on failure for diagnosis)","typeGuard":"// Verify transport matches: do not mix plaintext and TLS\nbool useTls = serverRequiresTls;\nvar ssl = useTls ? new SslClientAuthenticationOptions { TargetHost = host } : null;","tryCatchPattern":"try { var reply = session.Execute(cmd); }\ncatch (Exception ex) when (ex.Message.Contains(\"Unexpected response\")) { logger?.LogError(\"protocol mismatch: {Msg}\", ex.Message); /* reconnect or abort */ }","preventionTips":["Connect only to Garnet/Redis RESP servers.","Match TLS/plaintext between client and server.","Align RESP protocol versions across client and server.","Log raw reply bytes to diagnose the unexpected server message."],"tags":["csharp","resp-protocol","network","parsing","garnet-client-session"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}