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
- Ensure start() is called (and succeeds) before stop() on the same LookupCoordinatorManager instance
- Guard stop() calls with the lifecycle state, e.g. only stop if the coordinator was started
- Avoid double-stopping: track shutdown state at the caller level or use Druid's Lifecycle management so stop is invoked exactly once
- 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
- Always pair start()/stop() on the same instance and track the started state
- Register the manager with a Druid Lifecycle so shutdown ordering is handled automatically
- In tests, call start() in @BeforeEach and stop() in @AfterEach exactly once
- Never call stop() in a failure path of a failed start()
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)