eclipse-vertx/vert.x · error · IllegalStateException

Client is closed

Error message

Client is closed

What it means

HttpClientBase.checkClosed throws IllegalStateException when the client's close sequence has already started and an operation (request creation, connect, websocket, etc.) is attempted on the closed client. Vert.x clients are not reusable after close.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/http/impl/HttpClientBase.java:134

    options = options.copy();
    setDefaultSslOptions(options);
    return Future.succeededFuture(true);
  }

  protected abstract void setDefaultSslOptions(ClientSSLOptions options);

  public HttpClientBase proxyFilter(Predicate<SocketAddress> filter) {
    proxyFilter = filter;
    return this;
  }

  public VertxInternal vertx() {
    return vertx;
  }

  protected void checkClosed() {
    if (closeSequence.started()) {
      throw new IllegalStateException("Client is closed");
    }
  }
}

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Create a new HttpClient instance instead of using the closed one.
  2. Check client's closeFuture.isComplete() (or guard with isClosed state) before issuing requests.
  3. Ensure lifecycle ordering: stop schedulers/consumers before closing the client.
  4. Catch IllegalStateException and lazily recreate the client if closed.

Example fix

// before
client.close();
client.request(requestOptions); // IllegalStateException
// after
client.close();
HttpClient client = vertx.createHttpClient(options);
client.request(requestOptions);
Defensive patterns

Strategy: try-catch

Validate before calling

if (client.closeFuture().isComplete()) {
  client = vertx.createHttpClient(options);
}

Try / catch

try {
  request = client.request(opts);
} catch (IllegalStateException e) {
  client = vertx.createHttpClient(options);
  request = client.request(opts);
}

Prevention

When it happens

Trigger: Calling client.request(...) / websocket(...) / any operation after client.close() (or after the closeFuture completed); keeping a cached client instance used by a shutdown handler; closing the client in one callback while another request is still being initiated.

Common situations: Application shutdown racing with in-flight request creation; singleton client closed in a @PreDestroy/stop hook while a scheduler still fires requests; reusing a client obtained from a builder whose close future was resolved.

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/658f5690d27d30e7. Report an issue: GitHub.