{"record":{"id":"66797a2a11dfb5f6","repo":"apache/cassandra","slug":"wrong-protocol-direction-expected-s-got-s-for","errorCode":null,"errorMessage":"Wrong protocol direction (expected %s, got %s) for opcode %d (%s)","messagePattern":"Wrong protocol direction \\(expected (.+?), got (.+?)\\) for opcode (.+?) \\((.+?)\\)","errorType":"exception","errorClass":"org.apache.cassandra.transport.ProtocolException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/transport/Message.java","lineNumber":145,"sourceCode":"            }\n        }\n\n        Type(int opcode, Direction direction, Codec<?> codec)\n        {\n            this.opcode = opcode;\n            this.direction = direction;\n            this.codec = codec;\n        }\n\n        public static Type fromOpcode(int opcode, Direction direction)\n        {\n            if (opcode >= opcodeIdx.length)\n                throw new ProtocolException(String.format(\"Unknown opcode %d\", opcode));\n            Type t = opcodeIdx[opcode];\n            if (t == null)\n                throw new ProtocolException(String.format(\"Unknown opcode %d\", opcode));\n            if (t.direction != direction)\n                throw new ProtocolException(String.format(\"Wrong protocol direction (expected %s, got %s) for opcode %d (%s)\",\n                                                          t.direction,\n                                                          direction,\n                                                          opcode,\n                                                          t));\n            return t;\n        }\n\n        @VisibleForTesting\n        public Codec<?> unsafeSetCodec(Codec<?> codec) throws NoSuchFieldException, IllegalAccessException\n        {\n            Codec<?> original = this.codec;\n            Field field = Type.class.getDeclaredField(\"codec\");\n            field.setAccessible(true);\n            Field modifiers = ReflectionUtils.getModifiersField();\n            modifiers.setAccessible(true);\n            modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);\n            field.set(this, codec);\n            return original;","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/transport/Message.java#L127-L163","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix the client/driver so it only sends REQUEST-direction messages (opcodes like QUERY, PREPARE, EXECUTE) to the server.","Reconnect to resynchronize the byte stream; check for corruption in proxies or TLS termination layers.","Inspect the opcode values in packet captures to find where direction inversion occurs.","Upgrade the driver if a known direction-routing bug exists."],"exampleFix":"// before: client encodes a RESPONSE opcode in an outbound request frame\nint opcode = OpCode.RESULT; // direction RESPONSE\n// after: use request-direction opcodes when sending to the server\nint opcode = OpCode.QUERY; // direction REQUEST","handlingStrategy":"validation","validationCode":"// ensure the message type is request-direction before sending\nif (msg.type.direction != Direction.REQUEST) throw new IllegalStateException(\"cannot send \" + msg.type + \" to server\");","typeGuard":null,"tryCatchPattern":"try { session.execute(query); } catch (ProtocolException e) { log.error(\"Direction violation: {}\", e.getMessage()); reconnect(); }","preventionTips":["Only use request opcodes (QUERY/PREPARE/EXECUTE/STARTUP/OPTIONS/REGISTER/BATCH) toward the server","Keep driver and server versions compatible","Treat repeated occurrences as a corruption signal in the network path"],"tags":["cassandra","native-protocol","network"],"backgroundTag":"invalid-enum-value","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}