eclipse-vertx/vert.x · error · IllegalStateException
Request has already been read
Error message
Request has already been read
What it means
Thrown by checkEnded() in Http1ServerRequest whenever a request accessor (setExpectMultipart, body handlers, attributes, etc.) is invoked after the request has already been fully read/ended. Vert.x treats the request as a one-shot stream: once ended, its state can no longer be mutated.
Source
Thrown at vertx-core/src/main/java/io/vertx/core/http/impl/http1/Http1ServerRequest.java:661
}
if (handler != null) {
handler.handleException(t);
}
}
private void reportRequestReset(Throwable err) {
if (conn.httpMetrics != null) {
conn.httpMetrics.requestReset(metric);
}
VertxTracer tracer = context.tracer();
if (tracer != null) {
tracer.sendResponse(context, null, trace, err, TagExtractor.empty());
}
}
private void checkEnded() {
if (isEnded()) {
throw new IllegalStateException("Request has already been read");
}
}
private MultiMap attributes() {
// Create it lazily
if (attributes == null) {
attributes = MultiMap.caseInsensitiveMultiMap();
}
return attributes;
}
@Override
public HttpServerRequest streamPriorityHandler(Handler<StreamPriority> handler) {
return this;
}
@Override
public DecoderResult decoderResult() {View on GitHub (pinned to fb308bd8c3)
Solutions
- Call setExpectMultipart(true) at the very start of the request handler, before any body read
- Only configure the request in the request handler, not in end/close callbacks
- Use request.body() (Future-based) once and reuse the resulting Buffer instead of mixing body handlers and configuration calls
Example fix
// before
request.bodyHandler(b -> { ... });
request.setExpectMultipart(true);
// after
request.setExpectMultipart(true);
request.bodyHandler(b -> { ... }); Defensive patterns
Strategy: validation
Validate before calling
if (!request.isEnded()) {
request.setExpectMultipart(true);
} Try / catch
try { request.setExpectMultipart(true); } catch (IllegalStateException e) { /* already read: use buffered body */ } Prevention
- Configure the request at the top of its handler
- Never configure the request from end/close callbacks
- Read the body only once per request
When it happens
Trigger: Calling setExpectMultipart(true) or other request configuration after endHandler/body completion has fired, e.g. configuring the request from the response end handler or a later callback.
Common situations: Reading the body once with bodyHandler and then calling setExpectMultipart; async callback ordering where the body already completed before configuration code runs.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Response has already been written
- Request already complete
- Cannot write an HTTP/2 frame over an HTTP/1.x connection
- HTTP/1.x connections don't support SETTINGS
- HTTP/1.x connections don't support PING
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/20caea06231fa60d.
Report an issue: GitHub.