eclipse-vertx/vert.x · error · IllegalStateException

Cannot set connectHandler when server is listening

Error message

Cannot set connectHandler when server is listening

What it means

NetServerImpl guards its connect handler against changes once the server has started accepting connections. The handler is wired into the accept pipeline at bind time, so replacing it on a listening server would leave the socket pipeline inconsistent. Vert.x throws IllegalStateException immediately rather than silently ignoring the call.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/net/impl/tcp/NetServerImpl.java:130

    this.fileRegionEnabled = fileRegionEnabled;
    this.registerWriteHandler = registerWriteHandler;
    this.sslOptions = sslOptions;
    this.sslEngineOptions = sslEngineOptions;
  }

  public ServerSslContextProvider sslContextProvider() {
    return sslContextProviderRef.get();
  }

  @Override
  public synchronized Handler<NetSocket> connectHandler() {
    return handler;
  }

  @Override
  public synchronized NetServerImpl connectHandler(Handler<NetSocket> handler) {
    if (isListening()) {
      throw new IllegalStateException("Cannot set connectHandler when server is listening");
    }
    this.handler = handler;
    return this;
  }

  @Override
  public synchronized NetServerImpl exceptionHandler(Handler<Throwable> handler) {
    if (isListening()) {
      throw new IllegalStateException("Cannot set exceptionHandler when server is listening");
    }
    this.exceptionHandler = handler;
    return this;
  }

  public int actualPort() {
    NetServerImpl server = actualServer;
    return server != null ? server.actualPort : actualPort;
  }

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Set the connect handler before calling listen()
  2. Create a new NetServer instance with the desired handler and listen on the same address after closing the old one
  3. Inside the handler, dispatch to a mutable delegate so runtime changes swap the delegate, not the handler

Example fix

// before
server.listen();
server.connectHandler(sock -> handle(sock)); // IllegalStateException
// after
NetServer server = vertx.createNetServer();
server.connectHandler(sock -> handle(sock));
server.listen(1234);
Defensive patterns

Strategy: validation

Validate before calling

if (server instanceof NetServerImpl impl ? !impl.isListening() : !configured) {
  server.connectHandler(handler);
} else {
  throw new IllegalStateException("Cannot reconfigure a listening server");
}

Try / catch

try {
  server.connectHandler(handler);
} catch (IllegalStateException e) {
  // server already listening: recreate or use a delegate handler
}

Prevention

When it happens

Trigger: Calling netServer.connectHandler(handler) after listen() has been called and while isListening() is still true.

Common situations: Reusing a server instance to swap connection logic at runtime; shared utility code that configures a server without knowing its listen state; framework integrations that re-apply handler configuration on reload.

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