eclipse-vertx/vert.x · error · IllegalStateException
Listen already called
Error message
Listen already called
What it means
Each NetServer instance can bind exactly once. The internal 'listening' flag is set in bind(), and any subsequent bind attempt on the same instance throws IllegalStateException. To listen again you must create a new server instance.
Source
Thrown at vertx-core/src/main/java/io/vertx/core/net/impl/tcp/NetServerImpl.java:387
long checkIntervalForStatsInMillis = options.getCheckIntervalForStatsTimeUnit().toMillis(options.getCheckIntervalForStats());
trafficShapingHandler.configure(options.getOutboundGlobalBandwidth(), options.getInboundGlobalBandwidth(), checkIntervalForStatsInMillis);
if (options.getPeakOutboundGlobalBandwidth() != 0) {
trafficShapingHandler.setMaxGlobalWriteSize(options.getPeakOutboundGlobalBandwidth());
}
if (options.getMaxDelayToWait() != 0) {
long maxDelayToWaitInMillis = options.getMaxDelayToWaitTimeUnit().toMillis(options.getMaxDelayToWait());
trafficShapingHandler.setMaxWriteDelay(maxDelayToWaitInMillis);
}
promise.complete(true);
} else {
log.info("Not updating traffic shaping options as they have not changed");
promise.complete(false);
}
}
private synchronized Future<Channel> bind(ContextInternal context, SocketAddress localAddress) {
if (listening) {
throw new IllegalStateException("Listen already called");
}
this.listening = true;
this.eventLoop = context.nettyEventLoop();
SocketAddress bindAddress;
Map<ServerID, NetServerInternal> sharedNetServers = vertx.sharedTcpServers();
synchronized (sharedNetServers) {
actualPort = localAddress.port();
String hostOrPath = localAddress.isInetSocket() ? localAddress.host() : localAddress.path();
NetServerImpl main;
boolean shared;
ServerID id;
if (actualPort > 0 || localAddress.isDomainSocket()) {
id = new ServerID(actualPort, hostOrPath);
main = (NetServerImpl) sharedNetServers.get(id);
shared = true;
bindAddress = localAddress;View on GitHub (pinned to fb308bd8c3)
Solutions
- Call listen() only once per NetServer; create a new instance via vertx.createNetServer() for re-listen or retry
- Close the existing server (server.close()) and create a fresh instance before listening again
- Move listen() out of retry loops and retry only the surrounding business logic
Example fix
// before server.listen(1234); server.listen(1234); // IllegalStateException: Listen already called // after server.listen(1234); NetServer second = vertx.createNetServer(); second.connectHandler(server.connectHandler()); // or reconfigure second.listen(1234);
Defensive patterns
Strategy: validation
Validate before calling
AtomicBoolean started = new AtomicBoolean();
if (started.compareAndSet(false, true)) {
server.listen(port);
} Try / catch
try {
server.listen(port);
} catch (IllegalStateException e) {
if (!e.getMessage().contains("Listen already called")) throw e;
// ignore: already listening
} Prevention
- Treat NetServer as single-use: one listen per instance
- For retries/restarts, close then create a fresh server via vertx.createNetServer()
- Guard listen() behind an idempotent start() method
When it happens
Trigger: Calling listen() twice on the same NetServer; retrying listen after a failure without recreating the server; code paths that can invoke listen more than once (e.g. restart logic).
Common situations: Application restart/redeploy logic reusing the server object; retry wrappers around listen(); tests that call listen in setup and per test method on a shared instance.
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 connectHandler when server is listening
- Cannot set exceptionHandler when server is listening
- Set connect handler first
- Parsing already done
- blockedThreadCheckInterval must be > 0
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/c96ed9b993549d9b.
Report an issue: GitHub.