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

  1. Fix the client to only send REQUEST-direction messages over connections to the server.
  2. Reconnect to resynchronize; inspect intermediary proxies for frame corruption.
  3. Block or rate-limit untrusted clients hitting the native port; treat this as a protocol violation from that peer.
  4. 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

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


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/69cceeb0bad53626. Report an issue: GitHub.