apache/druid · warning

Interrupted during close()

Error message

Interrupted during close()

What it means

StreamAppenderator.close() waits for futures that abandon all persisted segments; if the waiting thread is interrupted, this warning is logged (after restoring the interrupt flag) and close continues to cleanup. Some segments may not have been properly abandoned/dropped.

Solutions

  1. Let the interrupt propagate normally — the code restores the flag and continues; verify leftover segments are cleaned by kill tasks
  2. If leftovers recur, run a kill task for the datasource's unused segments
  3. Avoid interrupting close(); call close on shutdown only after cancel flags are set gracefully
  4. Check logs for the companion 'Unable to abandon existing segments' warning for actual cleanup failures
Defensive patterns

Strategy: try-catch

Try / catch

try {
  appenderator.close();
} catch (RuntimeException e) {
  log.warn(e, "appenderator close interrupted or failed; relying on kill tasks for cleanup");
}

Prevention

When it happens

Trigger: The thread calling StreamAppenderator.close() is interrupted while blocked on Futures.allAsList(futures).get() — e.g. task shutdown interrupting the peon thread, or a supervisor canceling the thread mid-close.

Common situations: Overlord/taskkill issuing interrupts during task shutdown; ingestion task killed while closing its appenderator; timeouts that interrupt cleanup paths.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/ed6fb246a5e327bc. Report an issue: GitHub.

Appendix: source

Thrown at server/src/main/java/org/apache/druid/segment/realtime/appenderator/StreamAppenderator.java:1056

  {
    if (!closed.compareAndSet(false, true)) {
      log.debug("Appenderator already closed, skipping close() call.");
      return;
    }

    log.debug("Shutting down...");

    final List<ListenableFuture<?>> futures = new ArrayList<>();
    for (Map.Entry<SegmentIdWithShardSpec, Sink> entry : sinks.entrySet()) {
      futures.add(abandonSegment(entry.getKey(), entry.getValue(), false));
    }

    try {
      Futures.allAsList(futures).get();
    }
    catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      log.warn(e, "Interrupted during close()");
    }
    catch (ExecutionException e) {
      log.warn(e, "Unable to abandon existing segments during close()");
    }

    try {
      shutdownExecutors();
      Preconditions.checkState(
          persistExecutor == null || persistExecutor.awaitTermination(365, TimeUnit.DAYS),
          "persistExecutor not terminated"
      );
      Preconditions.checkState(
          pushExecutor == null || pushExecutor.awaitTermination(365, TimeUnit.DAYS),
          "pushExecutor not terminated"
      );
      Preconditions.checkState(
          intermediateTempExecutor == null || intermediateTempExecutor.awaitTermination(365, TimeUnit.DAYS),
          "intermediateTempExecutor not terminated"

View on GitHub (pinned to 9b90983fd2)