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

  1. Call setExpectMultipart(true) at the very start of the request handler, before any body read
  2. Only configure the request in the request handler, not in end/close callbacks
  3. 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

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


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/20caea06231fa60d. Report an issue: GitHub.