apache/druid · error · IllegalStateException

can't stop.

Error message

can't stop.

What it means

Thrown by CoordinatorPollingBasicAuthenticatorCacheManager.stop when lifecycleLock.canStop() returns false. stop() may only be called when the component is actually in a started state; calling stop before start, twice in a row, or concurrently fails this guard with an ISE. It signals an illegal lifecycle transition, not a shutdown problem per se.

Source

Thrown at extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authentication/db/cache/CoordinatorPollingBasicAuthenticatorCacheManager.java:150

            catch (Throwable t) {
              LOG.makeAlert(t, "Error occurred while polling for cachedUserMaps.").emit();
            }
          }
      );

      lifecycleLock.started();
      LOG.info("Started CoordinatorPollingBasicAuthenticatorCacheManager.");
    }
    finally {
      lifecycleLock.exitStart();
    }
  }

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

    LOG.info("CoordinatorPollingBasicAuthenticatorCacheManager is stopping.");
    exec.shutdownNow();
    LOG.info("CoordinatorPollingBasicAuthenticatorCacheManager is stopped.");
  }

  @Override
  public void handleAuthenticatorUserMapUpdate(String authenticatorPrefix, byte[] serializedUserMap)
  {
    LOG.debug("Received user cache update for authenticator [%s].", authenticatorPrefix);
    Preconditions.checkState(lifecycleLock.awaitStarted(1, TimeUnit.MILLISECONDS));
    try {
      cachedUserMaps.put(
          authenticatorPrefix,
          objectMapper.readValue(
              serializedUserMap,
              BasicAuthUtils.AUTHENTICATOR_USER_MAP_TYPE_REFERENCE

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Ensure stop() is only called after a successful start() on the same instance
  2. Make stop idempotent by tracking stopped state in the caller or fixing the lifecycle lock usage
  3. In tests, always start before stopping and stop once per lifecycle
  4. Wrap shutdown logic so it checks lifecycle state rather than assuming the manager is running

Example fix

// before
manager.stop(); manager.stop(); // second call throws
// after
if (running) { manager.stop(); running = false; }
Defensive patterns

Strategy: try-catch

Validate before calling

boolean stopIfRunning(AtomicBoolean running, CoordinatorPollingBasicAuthenticatorCacheManager m) { if (!running.get()) return false; m.stop(); running.set(false); return true; }

Try / catch

try { manager.stop(); } catch (ISE e) { LOG.info("stop ignored: manager not in started state"); }

Prevention

When it happens

Trigger: stop() called before start(); stop() called twice; concurrent stop from two threads after the first already claimed the transition; failing to await completion of a prior stop lifecycle stage.

Common situations: Test code (e.g. test_stop_interruptsPollingThread) invoking stop out of order; shutdown hooks firing after an earlier stop; leadership loss handling that stops 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/0fafa4fd788db4a3. Report an issue: GitHub.