apache/cassandra · error · ProtocolException
Unexpected RESPONSE message %s, expecting REQUEST
Error message
Unexpected RESPONSE message %s, expecting REQUEST
What it means
ProtocolException thrown by Message.Decoder's RequestDecoder when a decoded frame is a RESPONSE-direction message even though the server-side decoder only accepts REQUEST messages. Each connection side has a decoder for the direction it should receive; receiving the opposite direction means the peer is speaking out of turn. The frame is rejected before any handler runs.
Source
Thrown at src/java/org/apache/cassandra/transport/Message.java:490
else
{
assert message instanceof Response;
if (isTracing)
((Response) message).setTracingId(tracingId);
if (hasWarning)
((Response) message).setWarnings(warnings);
}
return message;
}
abstract M decode(Channel channel, Envelope inbound);
private static class RequestDecoder extends Decoder<Request>
{
Request decode(Channel channel, Envelope request)
{
if (request.header.type.direction != Direction.REQUEST)
throw new ProtocolException(String.format("Unexpected RESPONSE message %s, expecting REQUEST",
request.header.type));
return (Request) decodeMessage(channel, request);
}
}
private static class ResponseDecoder extends Decoder<Response>
{
Response decode(Channel channel, Envelope response)
{
if (response.header.type.direction != Direction.RESPONSE)
throw new ProtocolException(String.format("Unexpected REQUEST message %s, expecting RESPONSE",
response.header.type));
return (Response) decodeMessage(channel, response);
}
}
}View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Fix the client to only send REQUEST-direction messages over connections to the server.
- Reconnect to resynchronize; inspect intermediary proxies for frame corruption.
- Block or rate-limit untrusted clients hitting the native port; treat this as a protocol violation from that peer.
- Verify driver version compatibility with the server's protocol.
Example fix
// before: custom client writes back the server's RESULT message channel.writeAndFlush(resultMessage); // direction RESPONSE // after: only send request messages upstream channel.writeAndFlush(new QueryMessage(cql, ConsistencyLevel.ONE)); // direction REQUEST
Defensive patterns
Strategy: try-catch
Try / catch
try { frame = decodeFrame(buf); } catch (ProtocolException e) { metrics.protocolViolations.inc(); closeChannelQuietly(); } Prevention
- Never route response messages back to the server
- Reconnect on any protocol error — the stream cannot recover in place
- Inspect proxies if these errors appear in bursts
When it happens
Trigger: RequestDecoder.decode receives an Envelope whose header.type.direction != Direction.REQUEST, i.e. a client sent a message type such as RESULT or ERROR to the server.
Common situations: A buggy custom client echoing server responses back, stream corruption from a proxy, fuzzing/malicious traffic on the native port, or wrong-direction opcodes in hand-written clients.
Related errors
- Wrong protocol direction (expected %s, got %s) for opcode %d
- Unexpected REQUEST message %s, expecting RESPONSE
- Configured ${configName} "${intf}" could not be found
- Configured ${configName} "${intf}" was found, but had no add
- Configured ${configName} "${intf}" caused an exception
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/69cceeb0bad53626.
Report an issue: GitHub.