apache/cassandra · error · ProtocolException

Unexpected REQUEST message %s, expecting RESPONSE

Error message

Unexpected REQUEST message %s, expecting RESPONSE

What it means

ProtocolException thrown by Message.Decoder's ResponseDecoder when a frame is a REQUEST-direction message on a connection where RESPONSE messages are expected — i.e. the server's own outbound/response decoding path received something shaped like a client request. It guards the symmetry of the protocol: each side must send only its assigned direction. The frame is rejected before processing.

Source

Thrown at src/java/org/apache/cassandra/transport/Message.java:502

        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);
            }
        }
    }

    private static final Decoder.RequestDecoder REQUEST_DECODER = new Decoder.RequestDecoder();
    private static final Decoder.ResponseDecoder RESPONSE_DECODER = new Decoder.ResponseDecoder();

    static Decoder<Message.Request> requestDecoder()
    {
        return REQUEST_DECODER;
    }

    static Decoder<Message.Response> responseDecoder()
    {
        return RESPONSE_DECODER;

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Ensure the decoding side actually expects responses (use RequestDecoder on the server, ResponseDecoder only on client-side connections).
  2. Fix the peer that is sending REQUEST-direction messages on a response channel.
  3. Reconnect to resynchronize corrupted streams.
  4. Check test/integration harnesses for swapped decoder wiring.

Example fix

// before: client-side pipeline decodes with the wrong decoder
pipeline.addLast(new Message.Decoder.ResponseDecoder()); // server sends us responses, wrong slot
// after: clients decode responses, requests are only what we send
pipeline.addLast(new Message.Decoder.RequestDecoder()); // as a server receiving requests
Defensive patterns

Strategy: try-catch

Try / catch

try { frame = decoder.decode(ch, envelope); } catch (ProtocolException e) { log.warn("Wrong-direction frame from peer: {}", e.getMessage()); close(ch); }

Prevention

When it happens

Trigger: ResponseDecoder.decode receives an Envelope whose header.type.direction != Direction.RESPONSE, typically when a server-side component (e.g. an internode or testing client) decodes an inbound frame containing QUERY, STARTUP, etc. where a response was expected.

Common situations: Using the server's internal client classes against a peer that sends requests back, corrupted frames in-flight, or test harnesses wiring decoders on the wrong side of a connection.

Related errors


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