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
- Set the connect handler before calling listen()
- Create a new NetServer instance with the desired handler and listen on the same address after closing the old one
- 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
- Configure all handlers immediately after vertx.createNetServer(), before listen()
- Use a delegate/mutable-handler pattern if runtime swapping is needed
- Centralize server construction in one factory that enforces ordering
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
- Cannot set exceptionHandler when server is listening
- Set connect handler first
- Listen already called
- Parsing already done
- Already started
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/c90c5e4cc021c206.
Report an issue: GitHub.