{"record":{"id":"bb41b457588ac42d","repo":"apache/cassandra","slug":"invalid-message-version-got-s-but-previous-messa","errorCode":null,"errorMessage":"Invalid message version. Got %s but previous messages on this connection had version %s","messagePattern":"Invalid message version\\. Got (.+?) but previous messages on this connection had version (.+?)","errorType":"exception","errorClass":"ProtocolException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/transport/PreV5Handlers.java","lineNumber":295,"sourceCode":"\n    /**\n     * Simple adaptor to allow {@link org.apache.cassandra.transport.Message.Decoder#decodeMessage(Channel, Envelope)}\n     * to be used as a handler in pre-V5 pipelines\n     */\n    @ChannelHandler.Sharable\n    public static class ProtocolDecoder extends MessageToMessageDecoder<Envelope>\n    {\n        public static final ProtocolDecoder instance = new ProtocolDecoder();\n        private ProtocolDecoder(){}\n\n        public void decode(ChannelHandlerContext ctx, Envelope source, List<Object> results)\n        {\n            try\n            {\n                ProtocolVersion version = getConnectionVersion(ctx);\n                if (source.header.version != version)\n                {\n                    throw new ProtocolException(\n                        String.format(\"Invalid message version. Got %s but previous \" +\n                                      \"messages on this connection had version %s\",\n                                      source.header.version, version));\n                }\n                results.add(Message.Decoder.decodeMessage(ctx.channel(), source));\n            }\n            catch (Throwable ex)\n            {\n                source.release();\n                // Remember the streamId\n                throw ErrorMessage.wrap(ex, source.header.streamId);\n            }\n        }\n    }\n\n    /**\n     * Simple adaptor to plug CQL message encoding into pre-V5 pipelines\n     */","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/transport/PreV5Handlers.java#L277-L313","documentation":"ProtocolException thrown by the pre-v5 Envelope.Decoder when a frame's protocol version differs from the version already established on that connection. Native protocol versions are negotiated once (via STARTUP) and must remain constant for the connection's lifetime; a mid-connection version change means a desynchronized or malicious stream, so the frame is rejected.","triggerScenarios":"On a pre-v5 connection, decode obtains the connection's negotiated version (getConnectionVersion) and finds source.header.version != that version — e.g. after byte-stream desync, or a client suddenly sending frames with a different version byte than STARTUP declared.","commonSituations":"Stream corruption from proxies/NAT devices, clients that hardcode a version byte differing from their negotiated version, fuzzers, or mixing driver instances over a shared connection.","solutions":["Reconnect so the version is renegotiated via STARTUP and kept consistent.","Fix the client to use the negotiated ProtocolVersion object for every frame instead of a hardcoded version byte.","Check intermediaries (proxies, TLS offloaders) that may rewrite or corrupt frame headers.","Update the driver to a version that pins frames to the negotiated version."],"exampleFix":"// before: hardcoded version byte in client frame writer\nout.writeByte(3); // v3 regardless of negotiation\n// after: write the negotiated version\nout.writeByte(connection.getProtocolVersion().asInt());","handlingStrategy":"validation","validationCode":"// client: assert every frame uses the negotiated version\ncheckState(negotiatedVersion == frameVersion, \"frame version %s != negotiated %s\", frameVersion, negotiatedVersion);","typeGuard":null,"tryCatchPattern":"try { decode(buf); } catch (ProtocolException e) { if (e.getMessage().contains(\"Invalid message version\")) { reconnectWithRenegotiation(); } }","preventionTips":["Always write frames with the negotiated ProtocolVersion, never a hardcoded byte","Investigate proxies if version bytes change mid-stream","Reconnect immediately — version changes cannot be recovered mid-connection"],"tags":["cassandra","native-protocol","version-compatibility"],"backgroundTag":"version-mismatch","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"}