{"record":{"id":"b99d895c97630711","repo":"quarkusio/quarkus","slug":"response-head-already-sent-with-chunked-response","errorCode":null,"errorMessage":"Response head already sent with chunked=${response.isChunked()}, cannot change to chunked=${chunked}","messagePattern":"Response head already sent with chunked=(.+?), cannot change to chunked=(.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxResteasyReactiveRequestContext.java","lineNumber":488,"sourceCode":"    @Override\n    public boolean closed() {\n        return response.ended() || response.closed();\n    }\n\n    @Override\n    public ServerHttpResponse setChunked(boolean chunked) {\n        if (!response.headWritten()) {\n            try {\n                response.setChunked(chunked);\n            } catch (IllegalStateException e) {\n                // TOCTOU: head was concurrently written between our check and setChunked();\n                // verify the already-sent value matches what we wanted to set\n                if (response.isChunked() != chunked) {\n                    throw e;\n                }\n            }\n        } else if (response.isChunked() != chunked) {\n            throw new IllegalStateException(\n                    \"Response head already sent with chunked=\" + response.isChunked()\n                            + \", cannot change to chunked=\" + chunked);\n        }\n        return this;\n    }\n\n    @Override\n    public ServerHttpResponse write(byte[] data, Consumer<Throwable> asyncResultHandler) {\n        response.write(Buffer.buffer(data)).onComplete(event -> {\n            if (event.failed()) {\n                asyncResultHandler.accept(event.cause());\n            } else {\n                asyncResultHandler.accept(null);\n            }\n        });\n        return this;\n    }\n","sourceCodeStart":470,"sourceCodeEnd":506,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxResteasyReactiveRequestContext.java#L470-L506","documentation":"VertxResteasyReactiveRequestContext.setChunked() throws IllegalStateException when the response head has already been sent and the requested chunked flag differs from the chunked value already committed in the response head. HTTP headers (including Transfer-Encoding: chunked) cannot be changed after the head is written.","triggerScenarios":"Calling setChunked(true/false) after the response head was written with the opposite chunked setting — e.g. mixing streaming (chunked) responses with content-length writes, or setting chunked after partial response output.","commonSituations":"Custom message body writers or filters that toggle chunked mode after another component started writing the response; returning a StreamingOutput after headers were flushed; double-write bugs in interceptors.","solutions":["Call setChunked() before any response data is written (before the head is flushed).","Make the chunked decision consistent in one place — don't mix a chunked writer with a content-length based write.","Inspect interceptors/filters/writers for a path that writes the response head earlier than expected."],"exampleFix":"// before\nresponse.write(data); // head flushed chunked=false\ncontext.setChunked(true); // IllegalStateException\n// after\ncontext.setChunked(true);\nresponse.write(data);","handlingStrategy":"validation","validationCode":"if (context.serverResponse().headWritten()) {\n    throw new IllegalStateException(\"Response head already written; cannot change chunked mode\");\n}\ncontext.setChunked(true);","typeGuard":null,"tryCatchPattern":"try {\n    context.setChunked(true);\n} catch (IllegalStateException e) {\n    // head already committed with different chunked flag; leave as-is\n}","preventionTips":["Decide chunked mode once, before writing any response data.","Avoid mixing content-length writes with setChunked(true).","Audit interceptors/filters for early response writes."],"tags":["http","chunked","response-state","headers"],"backgroundTag":"response-committed","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}