quarkusio/quarkus · error · IllegalStateException
Response head already sent with chunked=${response.isChunked
Error message
Response head already sent with chunked=${response.isChunked()}, cannot change to chunked=${chunked} What it means
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.
Source
Thrown at independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxResteasyReactiveRequestContext.java:488
@Override
public boolean closed() {
return response.ended() || response.closed();
}
@Override
public ServerHttpResponse setChunked(boolean chunked) {
if (!response.headWritten()) {
try {
response.setChunked(chunked);
} catch (IllegalStateException e) {
// TOCTOU: head was concurrently written between our check and setChunked();
// verify the already-sent value matches what we wanted to set
if (response.isChunked() != chunked) {
throw e;
}
}
} else if (response.isChunked() != chunked) {
throw new IllegalStateException(
"Response head already sent with chunked=" + response.isChunked()
+ ", cannot change to chunked=" + chunked);
}
return this;
}
@Override
public ServerHttpResponse write(byte[] data, Consumer<Throwable> asyncResultHandler) {
response.write(Buffer.buffer(data)).onComplete(event -> {
if (event.failed()) {
asyncResultHandler.accept(event.cause());
} else {
asyncResultHandler.accept(null);
}
});
return this;
}
View on GitHub (pinned to e1c734241f)
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.
Example fix
// before response.write(data); // head flushed chunked=false context.setChunked(true); // IllegalStateException // after context.setChunked(true); response.write(data);
Defensive patterns
Strategy: validation
Validate before calling
if (context.serverResponse().headWritten()) {
throw new IllegalStateException("Response head already written; cannot change chunked mode");
}
context.setChunked(true); Try / catch
try {
context.setChunked(true);
} catch (IllegalStateException e) {
// head already committed with different chunked flag; leave as-is
} Prevention
- Decide chunked mode once, before writing any response data.
- Avoid mixing content-length writes with setChunked(true).
- Audit interceptors/filters for early response writes.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Malformed parameter:
- should have comma
- IOException(e)
- OIDC discovery endpoint request failed
- Proxy type HTTP is required
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/b99d895c97630711.
Report an issue: GitHub.