apache/cassandra · error · org.apache.cassandra.transport.ProtocolException

Wrong protocol direction (expected %s, got %s) for opcode %d

Error message

Wrong protocol direction (expected %s, got %s) for opcode %d (%s)

What it means

ProtocolException thrown by Message.Type.fromOpcode when the decoded opcode is valid but its direction (REQUEST vs RESPONSE) does not match the direction expected for the frame being decoded. Requests must flow client->server and responses server->client; a mismatch indicates a garbled or misdirected frame. The server aborts decoding rather than processing a frame of the wrong kind.

Source

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

            }
        }

        Type(int opcode, Direction direction, Codec<?> codec)
        {
            this.opcode = opcode;
            this.direction = direction;
            this.codec = codec;
        }

        public static Type fromOpcode(int opcode, Direction direction)
        {
            if (opcode >= opcodeIdx.length)
                throw new ProtocolException(String.format("Unknown opcode %d", opcode));
            Type t = opcodeIdx[opcode];
            if (t == null)
                throw new ProtocolException(String.format("Unknown opcode %d", opcode));
            if (t.direction != direction)
                throw new ProtocolException(String.format("Wrong protocol direction (expected %s, got %s) for opcode %d (%s)",
                                                          t.direction,
                                                          direction,
                                                          opcode,
                                                          t));
            return t;
        }

        @VisibleForTesting
        public Codec<?> unsafeSetCodec(Codec<?> codec) throws NoSuchFieldException, IllegalAccessException
        {
            Codec<?> original = this.codec;
            Field field = Type.class.getDeclaredField("codec");
            field.setAccessible(true);
            Field modifiers = ReflectionUtils.getModifiersField();
            modifiers.setAccessible(true);
            modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
            field.set(this, codec);
            return original;

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Fix the client/driver so it only sends REQUEST-direction messages (opcodes like QUERY, PREPARE, EXECUTE) to the server.
  2. Reconnect to resynchronize the byte stream; check for corruption in proxies or TLS termination layers.
  3. Inspect the opcode values in packet captures to find where direction inversion occurs.
  4. Upgrade the driver if a known direction-routing bug exists.

Example fix

// before: client encodes a RESPONSE opcode in an outbound request frame
int opcode = OpCode.RESULT; // direction RESPONSE
// after: use request-direction opcodes when sending to the server
int opcode = OpCode.QUERY; // direction REQUEST
Defensive patterns

Strategy: validation

Validate before calling

// ensure the message type is request-direction before sending
if (msg.type.direction != Direction.REQUEST) throw new IllegalStateException("cannot send " + msg.type + " to server");

Try / catch

try { session.execute(query); } catch (ProtocolException e) { log.error("Direction violation: {}", e.getMessage()); reconnect(); }

Prevention

When it happens

Trigger: fromOpcode is called with a direction (REQUEST or RESPONSE) that contradicts the opcode's registered direction — e.g. decoding an inbound server frame whose opcode is RESPONSE, or an outbound path receiving an opcode marked REQUEST.

Common situations: A client sending response-type messages to the server, stream corruption swapping frame bytes, a malicious or buggy peer flipping direction bits, or a driver routing responses back to the server.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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