apache/druid · error · IllegalStateException
is not started
Error message
${className} is not started What it means
SqlSegmentsMetadataManager throws this IllegalStateException from startPollingDatabasePeriodically() when the manager's periodic polling is requested but the manager lifecycle was never started via start(). Internally, the executor field (exec) is null, meaning start() was not called (or stop() already tore it down). It is a lifecycle-ordering guard: polling cannot be scheduled without the executor created during start().
Solutions
- Ensure the Druid Lifecycle (or startup injector) calls start() on SqlSegmentsMetadataManager before startPollingDatabasePeriodically().
- Check for double lifecycle management: some component may have called stop() before your startPollingDatabasePeriodically() call.
- In tests, call manager.start() in setup before enabling periodic polling.
- Wrap the call in a state check: only start polling when the manager reports started.
Example fix
// before sqlSegmentsMetadataManager.startPollingDatabasePeriodically(); // after sqlSegmentsMetadataManager.start(); // must precede polling start sqlSegmentsMetadataManager.startPollingDatabasePeriodically();
Defensive patterns
Strategy: validation
Validate before calling
// before enabling polling
if (manager.isStarted()) { // check the manager's own state if exposed
manager.startPollingDatabasePeriodically();
} Type guard
boolean canPoll = manager != null && java.util.concurrent.atomic status-check: poll only when exec-backed lifecycle has started;
Try / catch
try {
manager.startPollingDatabasePeriodically();
} catch (IllegalStateException e) {
// manager not started: initialize lifecycle first or reschedule
} Prevention
- Always start SqlSegmentsMetadataManager through the Druid Lifecycle before enabling polling
- Do not manually interleave start/stop with polling calls
- In tests, call start() in @BeforeEach/setup
When it happens
Trigger: Calling startPollingDatabasePeriodically() before start() has been invoked on the manager, or after stop() released the polling executor (exec == null) while holding the startStopPollLock write lock.
Common situations: Coordinator/Historical node wiring where the SqlSegmentsMetadataManager is injected but its Lifecycle was never started; custom code or tests that call startPollingDatabasePeriodically() directly without the Druid lifecycle; calling polling start after a shutdown hook already stopped the manager.
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/deef73a278667d41.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/main/java/org/apache/druid/metadata/SqlSegmentsMetadataManager.java:291
ReentrantReadWriteLock.WriteLock lock = startStopPollLock.writeLock();
lock.lock();
try {
exec.shutdownNow();
exec = null;
}
finally {
lock.unlock();
}
}
@Override
public void startPollingDatabasePeriodically()
{
ReentrantReadWriteLock.WriteLock lock = startStopPollLock.writeLock();
lock.lock();
try {
if (exec == null) {
throw new IllegalStateException(getClass().getName() + " is not started");
}
if (isPollingDatabasePeriodically()) {
return;
}
PeriodicDatabasePoll periodicDatabasePoll = new PeriodicDatabasePoll();
latestDatabasePoll = periodicDatabasePoll;
startPollingCount++;
currentStartPollingOrder = startPollingCount;
final long localStartOrder = currentStartPollingOrder;
periodicPollTaskFuture = exec.scheduleWithFixedDelay(
createPollTaskForStartOrder(localStartOrder, periodicDatabasePoll),
0,
periodicPollDelay.getMillis(),
TimeUnit.MILLISECONDS
);View on GitHub (pinned to 9b90983fd2)