apache/druid · error · IllegalStateException

LookupCoordinatorManager can't stop.

Error message

LookupCoordinatorManager can't stop.

What it means

LookupCoordinatorManager.stop() throws this IllegalStateException when the lifecycle lock reports the component cannot be stopped — i.e. stop() was called before start() ever succeeded, or after the component was already stopped. Druid uses LifecycleLock to enforce strict start/stop ordering on managed components; stopping an un-started or already-stopped coordinator is treated as a programming error rather than an idempotent no-op.

Solutions

  1. Ensure start() is called (and succeeds) before stop() on the same LookupCoordinatorManager instance
  2. Guard stop() calls with the lifecycle state, e.g. only stop if the coordinator was started
  3. Avoid double-stopping: track shutdown state at the caller level or use Druid's Lifecycle management so stop is invoked exactly once
  4. If start() failed, fix the underlying start error (injection/config) instead of calling stop() afterwards

Example fix

// before
manager.stop(); // called without ever starting
// after
if (!started) {
  manager.start();
}
manager.stop();
Defensive patterns

Strategy: try-catch

Validate before calling

if (manager != null && lifecycleLock.isStarted()) { /* safe to stop */ }

Type guard

boolean isStoppable(LifecycleLock lock) { return lock.isStarted() && !lock.isStopped(); }

Try / catch

try {
  manager.stop();
} catch (IllegalStateException e) {
  if (!e.getMessage().contains("can't stop")) throw e;
  LOG.debug("Coordinator already stopped or never started");
}

Prevention

When it happens

Trigger: Calling LookupCoordinatorManager.stop() when start() was never called, when a start() attempt failed midway leaving the lock in a non-started state, or calling stop() twice on the same instance. The listed tests exercise multiple start/stop cycles which can hit this if ordering is wrong.

Common situations: Wiring the coordinator into a Druid lifecycle in the wrong order, a failed start (e.g. injected HttpServerStartupError) followed by a stop attempt, unit tests that call stop() without start(), or double-shutdown of a server that stops the same manager twice.

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 apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/f31458864dce56f6. Report an issue: GitHub.

Appendix: source

Thrown at server/src/main/java/org/apache/druid/server/lookup/cache/LookupCoordinatorManager.java:457

        LOG.debug("Started");
      }
      catch (Exception ex) {
        LOG.makeAlert(ex, "Got Exception while start()").emit();
      }
      finally {
        //so that subsequent stop() would happen, even if start() failed with exception
        lifecycleLock.started();
        lifecycleLock.exitStart();
      }
    }
  }

  public void stop()
  {
    synchronized (lifecycleLock) {
      if (!lifecycleLock.canStop()) {
        throw new ISE("LookupCoordinatorManager can't stop.");
      }

      try {
        LOG.debug("Stopping");

        if (backgroundManagerFuture != null && !backgroundManagerFuture.cancel(true)) {
          LOG.warn("Background lookup manager thread could not be cancelled");
        }

        // signal the executorService to shut down ASAP, if this coordinator becomes leader again
        // then start() would ensure that this executorService is finished before starting a
        // new one.
        if (executorService != null) {
          executorService.shutdownNow();
        }

        LOG.debug("Stopped");
      }

View on GitHub (pinned to 9b90983fd2)