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;
  }

  @Override

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Remove explicit eventBus().start() calls and let the Vertx instance start the bus during deployment.
  2. Track whether start has been issued and skip a second call (idempotent bootstrap).
  3. 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

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


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/d84d39f23cc2b00a. Report an issue: GitHub.