{"record":{"id":"d31721aed2adabed","repo":"apache/cassandra","slug":"attempted-to-encode-a-response-with-an-unset-strea","errorCode":null,"errorMessage":"Attempted to encode a response with an unset stream id: ","messagePattern":"Attempted to encode a response with an unset stream id: ","errorType":"exception","errorClass":"ProtocolException","httpStatus":null,"severity":"critical","filePath":"src/java/org/apache/cassandra/transport/Message.java","lineNumber":347,"sourceCode":"            this.warnings = warnings;\n            return this;\n        }\n\n        public List<String> getWarnings()\n        {\n            return warnings;\n        }\n    }\n\n    public Envelope encode(ProtocolVersion version, int streamId)\n    {\n        // A Response's stream id must be stamped before it is serialized to the wire. UNSET_STREAM_ID here\n        // means a server code path produced a response without routing information; sending it would risk\n        // delivering it to an unrelated in-flight request (CASSANDRA-21508). Fail fatally so the connection\n        // is torn down rather than mis-route a response. Checked before the try below so it is not caught and\n        // re-wrapped (which would carry the unset id forward).\n        if (streamId == UNSET_STREAM_ID)\n            throw ProtocolException.toFatalException(new ProtocolException(\"Attempted to encode a response with an unset stream id: \" + this));\n\n        int flags = Flag.none();\n        @SuppressWarnings(\"unchecked\")\n        Codec<Message> codec = (Codec<Message>)this.type.codec;\n        try\n        {\n            int messageSize = codec.encodedSize(this, version);\n            ByteBuf body;\n            if (this instanceof Response)\n            {\n                Response message = (Response)this;\n                TimeUUID tracingId = message.getTracingId();\n                Map<String, ByteBuffer> customPayload = message.getCustomPayload();\n                if (tracingId != null)\n                    messageSize += TimeUUID.sizeInBytes();\n                List<String> warnings = message.getWarnings();\n                if (warnings != null)\n                {","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/transport/Message.java#L329-L365","documentation":"Fatal ProtocolException thrown when the native-protocol layer tries to encode a server Response whose streamId is still UNSET_STREAM_ID. A response must carry the stream id of the request it answers; an unset id means a server code path produced a response without routing information, and sending it could deliver it to an unrelated in-flight request (CASSANDRA-21508). The connection is torn down intentionally to avoid mis-routing.","triggerScenarios":"A server handler path creates a Response (e.g. an ERROR response or event) and writes it without calling setStreamId with the originating request's stream id — typically in custom/modified request handlers, early-failure paths that build responses before pairing with a request, or internal code paths responding outside the normal request dispatch.","commonSituations":"Running patched/unreleased Cassandra builds where a new error path forgets to stamp the stream id; a bug in driver-facing request handling causing connection resets; after CASSANDRA-21508, responses that previously would have been silently mis-routed now kill the connection with this exception in server logs.","solutions":["Find the server code path that created the Response and ensure streamId is set from the originating request before encoding (response.setStreamId(request.streamId)).","Check server logs for the stack trace preceding the connection teardown to identify the producing handler.","Upgrade to a version containing the fix for the specific handler bug (search JIRA for CASSANDRA-21508 follow-ups).","As a client-side mitigation, expect the connection to close and rely on driver reconnection/retry; the fatal exception is intentional protection.","If seen without any local patches, report with full server logs — it indicates an internal invariant violation."],"exampleFix":"// before\nMessage.Response resp = Message.response(type, message);\nchannel.writeAndFlush(resp); // stream id never set\n// after\nresp.setStreamId(message.getStreamId());\nchannel.writeAndFlush(resp);","handlingStrategy":"type-guard","validationCode":"// server-side guard before writing a response\nif (response.getStreamId() == Message.UNSET_STREAM_ID)\n    throw new IllegalStateException(\"Response written without stream id: \" + response);","typeGuard":"boolean hasRoutedStreamId(Message.Response r) { return r.getStreamId() != Message.UNSET_STREAM_ID; }","tryCatchPattern":null,"preventionTips":["Always derive responses from the request object so setStreamId(request.streamId) is not forgotten.","Add assertions/tests covering every error path that writes a Response.","On the client side, treat abrupt connection closes after an error as server-side routing failure and reconnect/retry idempotent requests."],"tags":["native-protocol","serialization","connection","server"],"backgroundTag":"internal-invariant-violation","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}