apache/druid · error · RejectedExecutionException

Service not started.

Error message

Service not started.

What it means

LoggingEmitter writes events to a log, but only after start() has been called; emit() synchronizes on the started AtomicBoolean and throws RejectedExecutionException('Service not started.') if emit is invoked before start(). Unlike HttpPostEmitter, it checks only started state at call time.

Source

Thrown at processing/src/main/java/org/apache/druid/java/util/emitter/core/LoggingEmitter.java:187

            log.info(message, started.get());
          }
          break;
        case WARN:
          log.warn(message, started.get());
          break;
        case ERROR:
          log.error(message, started.get());
          break;
      }
    }
  }

  @Override
  public void emit(Event event)
  {
    synchronized (started) {
      if (!started.get()) {
        throw new RejectedExecutionException("Service not started.");
      }
    }

    // Allowlist filtering: only applies to ServiceMetricEvents.
    // Non-metric events (alerts, etc.) always pass through.
    if (allowedMetrics != null && event instanceof ServiceMetricEvent) {
      final String metricName = ((ServiceMetricEvent) event).getMetric();
      if (!allowedMetrics.contains(metricName)) {
        return;
      }
    }

    try {
      switch (level) {
        case TRACE:
          if (log.isTraceEnabled()) {
            log.trace(MarkerFactory.getMarker(event.getFeed()), jsonMapper.writeValueAsString(event));
          }

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Call emitter.start() before any emit, typically via Druid Lifecycle initialization.
  2. In tests, invoke start() in setup or use the Lifecycle to manage the emitter.
  3. Catch RejectedExecutionException around emit if emission may occur before start.
  4. Ensure close()/stop() is only called after all producers have finished.

Example fix

// before
LoggingEmitter emitter = new LoggingEmitter(config, mapper);
emitter.emit(event); // RejectedExecutionException
// after
LoggingEmitter emitter = new LoggingEmitter(config, mapper);
emitter.start();
emitter.emit(event);
Defensive patterns

Strategy: try-catch

Validate before calling

// AtomicBoolean started is private; track your own start state
if (!emitterStarted) { startEmitterOrSkip(event); return; }

Try / catch

try {
  emitter.emit(event);
} catch (RejectedExecutionException e) {
  log.debug(e, "LoggingEmitter not started; dropping event");
}

Prevention

When it happens

Trigger: Calling emit(Event) on a LoggingEmitter whose start() was never invoked; emitting after close() reset the flag; constructing the emitter manually in tests or embedded code without calling start().

Common situations: Unit tests constructing LoggingEmitter without lifecycle start; wiring emitters into a custom ServiceMetrics config before Lifecycle start; using an emitter obtained from a stopped injector/Lifecycle.

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/f8046053fe087d03. Report an issue: GitHub.