apache/druid · error · IllegalStateException
can't stop.
Error message
can't stop.
What it means
Thrown by CoordinatorBasicAuthenticatorMetadataStorageUpdater.stop when lifecycleLock.canStop() returns false. stop() is only legal from the started state; calling it before start, twice, or concurrently triggers this ISE. The method would otherwise mark the updater stopped so subsequent user-map updates are rejected.
Source
Thrown at extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authentication/db/updater/CoordinatorBasicAuthenticatorMetadataStorageUpdater.java:213
LOG.makeAlert(t, "Error occurred while polling for cachedUserMaps.").emit();
}
return ScheduledExecutors.Signal.REPEAT;
}
}
);
lifecycleLock.started();
}
finally {
lifecycleLock.exitStart();
}
}
@LifecycleStop
public void stop()
{
if (!lifecycleLock.canStop()) {
throw new ISE("can't stop.");
}
LOG.info("CoordinatorBasicAuthenticatorMetadataStorageUpdater is stopping.");
stopped = true;
LOG.info("CoordinatorBasicAuthenticatorMetadataStorageUpdater is stopped.");
}
@Override
public void createUser(String prefix, String userName)
{
Preconditions.checkState(lifecycleLock.awaitStarted(1, TimeUnit.MILLISECONDS));
createUserInternal(prefix, userName);
}
@Override
public void deleteUser(String prefix, String userName)
{
Preconditions.checkState(lifecycleLock.awaitStarted(1, TimeUnit.MILLISECONDS));View on GitHub (pinned to 9b90983fd2)
Solutions
- Track started/stopped in the caller and skip redundant stop calls
- Ensure the lifecycle lock usage matches Druid conventions (canStop/stopInState)
- In tests, pair every start with exactly one stop in teardown
- If the updater is already stopped, treat further stops as no-ops
Example fix
// before
updater.stop(); updater.stop(); // second call throws
// after
if (started) { updater.stop(); started = false; } Defensive patterns
Strategy: try-catch
Validate before calling
if (!updaterStarted.get()) { return; } // only stop after successful start
updater.stop(); updaterStarted.set(false); Try / catch
try { updater.stop(); } catch (ISE e) { LOG.info("stop ignored: updater not started"); } Prevention
- Make stop idempotent with a started flag at the call site
- Don't register multiple stop hooks for the same updater
- In tests, teardown should stop at most once after a start
- Check lifecycle logs for prior stop events before stopping
When it happens
Trigger: stop() invoked without a prior successful start(); duplicate stop during shutdown; two threads racing to stop; lifecycle framework emitting stop events twice for one start.
Common situations: JVM shutdown hooks plus explicit lifecycle stop; test teardown stopping an already-stopped updater; leadership revocation handlers firing redundantly.
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/e36862eacf94d845.
Report an issue: GitHub.