microsoft/garnet · error · Exception

Unexpected response: {response}]

Error message

Unexpected response: {response}]

What it means

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.

Source

Thrown at libs/client/ClientSession/GarnetClientSession.cs:666

                        case (byte)'-':
                            error = true;
                            if (!RespReadResponseUtils.TryReadErrorAsString(out result, ref ptr, recvBufferPtr + bytesRead))
                                success = false;
                            break;

                        case (byte)'$':
                            if (!RespReadResponseUtils.TryReadStringWithLengthHeader(out result, ref ptr, recvBufferPtr + bytesRead))
                                success = false;
                            break;

                        case (byte)'*':
                            isArray = true;
                            if (!RespReadResponseUtils.TryReadStringArrayWithLengthHeader(out resultArray, ref ptr, recvBufferPtr + bytesRead))
                                success = false;
                            break;

                        default:
                            throw new Exception("Unexpected response: " + Encoding.UTF8.GetString(new Span<byte>(recvBufferPtr, bytesRead)).Replace("\n", "|").Replace("\r", "") + "]");
                    }
                }

                if (!success) return readHead;
                readHead = (int)(ptr - recvBufferPtr);

                Interlocked.Decrement(ref numCommands);
                if (isArray)
                {
                    var tcs = tcsArrayQueue.Dequeue();
                    tcs?.SetResult(resultArray);
                }
                else if (!RawResult)
                {
                    var tcs = tcsQueue.Dequeue();
                    if (error) tcs?.SetException(new Exception(result));
                    else tcs?.SetResult(result);
                }

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Verify the endpoint is actually a Garnet/Redis-compatible RESP server.
  2. Ensure TLS settings match between client and server (do not send plaintext to a TLS port or vice-versa).
  3. Capture the logged raw bytes to identify the unexpected server message — often reveals an AUTH error or wrong-protocol reply.
  4. Check for protocol version mismatches (RESP2 vs RESP3) and align client/server versions.

Example fix

// before — client not enabling TLS against a TLS-only server
var session = new GarnetClientSession(endpoint, sslOptions: null, ...);

// after — match the server's transport security
var session = new GarnetClientSession(endpoint,
    sslOptions: new SslClientAuthenticationOptions { TargetHost = host }, ...);
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the endpoint speaks RESP and TLS settings match before relying on replies
// (no in-band pre-check; capture raw bytes on failure for diagnosis)

Type guard

// Verify transport matches: do not mix plaintext and TLS
bool useTls = serverRequiresTls;
var ssl = useTls ? new SslClientAuthenticationOptions { TargetHost = host } : null;

Try / catch

try { var reply = session.Execute(cmd); }
catch (Exception ex) when (ex.Message.Contains("Unexpected response")) { logger?.LogError("protocol mismatch: {Msg}", ex.Message); /* reconnect or abort */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13). Data as JSON: /api/errors/166f122a172c23cd. Report an issue: GitHub.