apache/druid · error · RejectedExecutionException

Service is not started.

Error message

Service is not started.

What it means

HttpPostEmitter.awaitStarted() waits up to 1 second for the emitter's start latch. If the emitter was never started (or hasn't started within 1s), emit/flush attempts throw RejectedExecutionException 'Service is not started.' This prevents silently queuing events into an emitter that will never send them.

Source

Thrown at processing/src/main/java/org/apache/druid/java/util/emitter/core/HttpPostEmitter.java:205

  public void start()
  {
    synchronized (startLock) {
      if (!running) {
        if (startLatch.getCount() == 0) {
          throw new IllegalStateException("Already started.");
        }
        running = true;
        startLatch.countDown();
        emittingThread.start();
      }
    }
  }

  private void awaitStarted()
  {
    try {
      if (!startLatch.await(1, TimeUnit.SECONDS)) {
        throw new RejectedExecutionException("Service is not started.");
      }
      if (isTerminated()) {
        throw new RejectedExecutionException("Service is closed.");
      }
    }
    catch (InterruptedException e) {
      log.debug("Interrupted waiting for start");
      Thread.currentThread().interrupt();
      throw new RuntimeException(e);
    }
  }

  private boolean isTerminated()
  {
    return concurrentBatch.get() == null;
  }

  @Override

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Call emitter.start() before emitting or flushing any events
  2. Ensure startup isn't delayed beyond 1 second (check the EmittingThread for blocking initialization)
  3. Check for a prior close/termination that stopped the service; create a fresh emitter if needed
  4. Catch RejectedExecutionException around emit/flush to detect lifecycle misuse and requeue or log

Example fix

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

Strategy: try-catch

Validate before calling

if (!emitter.isStarted()) {
  emitter.start(); // or await startup before emitting
}

Try / catch

try {
  emitter.emit(event);
} catch (RejectedExecutionException e) {
  log.warn("Emitter not started; starting and re-emitting");
  emitter.start();
  emitter.emit(event);
}

Prevention

When it happens

Trigger: Calling emit(), flush() (via emitAndReturnBatch/flush -> awaitStarted) on an HttpPostEmitter before start() was called, or when start() has not completed within the 1-second await window.

Common situations: Forgetting lifecycle start in embedded usage; emitting immediately after construction; a blocked or slow startup thread exceeding the 1s latch timeout; emitter created but start() skipped in tests.

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