eclipse-vertx/vert.x · error · IllegalStateException
Already started
Error message
Already started
What it means
EventBusImpl.start(Promise) may only be called once per bus instance. If the 'started' flag is already true, it throws this IllegalStateException instead of silently starting twice, ensuring single initialization of reply-address infrastructure and metrics.
Source
Thrown at vertx-core/src/main/java/io/vertx/core/eventbus/impl/EventBusImpl.java:108
return outboundInterceptors;
}
@Override
public EventBus clusterSerializableChecker(Function<String, Boolean> classNamePredicate) {
codecManager.clusterSerializableCheck(classNamePredicate);
return this;
}
@Override
public EventBus serializableChecker(Function<String, Boolean> classNamePredicate) {
codecManager.serializableCheck(classNamePredicate);
return this;
}
@Override
public synchronized void start(Promise<Void> promise) {
if (started) {
throw new IllegalStateException("Already started");
}
started = true;
promise.complete();
}
@Override
public EventBus send(String address, Object message) {
return send(address, message, new DeliveryOptions());
}
@Override
public EventBus send(String address, Object message, DeliveryOptions options) {
MessageImpl msg = createMessage(true, isLocalOnly(options), address, options.getHeaders(), message, options.getCodecName());
sendOrPubInternal(msg, options, null);
return this;
}
@OverrideView on GitHub (pinned to fb308bd8c3)
Solutions
- Remove explicit eventBus().start() calls and let the Vertx instance start the bus during deployment.
- Track whether start has been issued and skip a second call (idempotent bootstrap).
- If the Vertx instance was closed, create a new Vertx rather than restarting the old one.
Example fix
// before
vertx.eventBus().start(promise); // second start on same bus
// after
if (!started.getAndSet(true)) {
vertx.eventBus().start(promise);
} Defensive patterns
Strategy: try-catch
Validate before calling
// track start calls yourself
private final AtomicBoolean busStarted = new AtomicBoolean();
if (busStarted.compareAndSet(false, true)) {
bus.start(promise);
} Try / catch
try {
bus.start(promise);
} catch (IllegalStateException e) {
// already started; complete immediately
promise.complete();
} Prevention
- Let the Vertx lifecycle start the event bus; avoid manual start() calls
- Make bootstrap idempotent with AtomicBoolean.compareAndSet
- Create a fresh Vertx instead of restarting a closed instance
When it happens
Trigger: Calling eventBus().start(promise) manually on an already-started bus, or Vert.xInternal start logic being invoked twice (e.g. from a custom Vertx bootstrap or restarting a closed Vertx instance).
Common situations: Application code that calls start() itself while the Vertx lifecycle already started the event bus; reusing a Vertx/EventBus instance after shutdown; embedding Vert.x in a framework that also calls start().
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
- Event Bus is not started
- Already a codec registered with name
- Already a default codec registered for class
- address not specified
- Server already bound
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/d84d39f23cc2b00a.
Report an issue: GitHub.