eclipse-vertx/vert.x · error · IllegalStateException

Cannot set chunked after data has been written on request

Error message

Cannot set chunked after data has been written on request

What it means

HttpClientRequestImpl.setChunked throws IllegalStateException once the request headers have already been sent (equivalently, after data has been written and flushed the headers). The transfer-encoding (chunked vs content-length) decision must be made before headers go on the wire, so later changes are rejected.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl.java:189

    this.maxRedirectBufferSize = maxRedirectBufferSize;
    return this;
  }

  @Override
  public synchronized int maxRedirectBufferSize() {
    return maxRedirectBufferSize;
  }

  @Override
  public int numberOfRedirections() {
    return numberOfRedirections;
  }

  @Override
  public synchronized HttpClientRequestImpl setChunked(boolean chunked) {
    checkEnded();
    if (headersSent) {
      throw new IllegalStateException("Cannot set chunked after data has been written on request");
    }
    // HTTP 1.0 does not support chunking so we ignore this if HTTP 1.0
    if (version() != io.vertx.core.http.HttpVersion.HTTP_1_0) {
      this.chunked = chunked;
    }
    return this;
  }

  @Override
  public synchronized boolean isChunked() {
    return chunked;
  }

  @Override
  public MultiMap headers() {
    return headers;
  }

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Call setChunked(true) immediately after creating the request and before any write/end call.
  2. Restructure so framing decisions (chunked vs content-length) are made before the first write.
  3. If body size is known upfront, set the Content-Length header instead of using chunked.

Example fix

// before
request.write(buffer);
request.setChunked(true); // IllegalStateException
// after
request.setChunked(true);
request.write(buffer);
Defensive patterns

Strategy: validation

Validate before calling

// always set framing before first write
HttpClientRequest req = client.request(opts).onSuccess(r -> {
  if (streaming) r.setChunked(true);
  r.write(body);
});

Prevention

When it happens

Trigger: Calling request.setChunked(true) after write(...) has been invoked (headers implicitly sent), or after an async write completed before setChunked was called; toggling chunked mode mid-body.

Common situations: Streaming code that writes first and configures framing afterwards; building a helper that sets chunked lazily after buffering decides to stream; race between write calls on different threads (method is synchronized but ordering still matters).

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/1048cda2daccbe5f. Report an issue: GitHub.