{"record":{"id":"ed6fb246a5e327bc","repo":"apache/druid","slug":"interrupted-during-close","errorCode":null,"errorMessage":"Interrupted during close()","messagePattern":"Interrupted during close\\(\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/src/main/java/org/apache/druid/segment/realtime/appenderator/StreamAppenderator.java","lineNumber":1056,"sourceCode":"  {\n    if (!closed.compareAndSet(false, true)) {\n      log.debug(\"Appenderator already closed, skipping close() call.\");\n      return;\n    }\n\n    log.debug(\"Shutting down...\");\n\n    final List<ListenableFuture<?>> futures = new ArrayList<>();\n    for (Map.Entry<SegmentIdWithShardSpec, Sink> entry : sinks.entrySet()) {\n      futures.add(abandonSegment(entry.getKey(), entry.getValue(), false));\n    }\n\n    try {\n      Futures.allAsList(futures).get();\n    }\n    catch (InterruptedException e) {\n      Thread.currentThread().interrupt();\n      log.warn(e, \"Interrupted during close()\");\n    }\n    catch (ExecutionException e) {\n      log.warn(e, \"Unable to abandon existing segments during close()\");\n    }\n\n    try {\n      shutdownExecutors();\n      Preconditions.checkState(\n          persistExecutor == null || persistExecutor.awaitTermination(365, TimeUnit.DAYS),\n          \"persistExecutor not terminated\"\n      );\n      Preconditions.checkState(\n          pushExecutor == null || pushExecutor.awaitTermination(365, TimeUnit.DAYS),\n          \"pushExecutor not terminated\"\n      );\n      Preconditions.checkState(\n          intermediateTempExecutor == null || intermediateTempExecutor.awaitTermination(365, TimeUnit.DAYS),\n          \"intermediateTempExecutor not terminated\"","sourceCodeStart":1038,"sourceCodeEnd":1074,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/segment/realtime/appenderator/StreamAppenderator.java#L1038-L1074","documentation":"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.","triggerScenarios":"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.","commonSituations":"Overlord/taskkill issuing interrupts during task shutdown; ingestion task killed while closing its appenderator; timeouts that interrupt cleanup paths.","solutions":["Let the interrupt propagate normally — the code restores the flag and continues; verify leftover segments are cleaned by kill tasks","If leftovers recur, run a kill task for the datasource's unused segments","Avoid interrupting close(); call close on shutdown only after cancel flags are set gracefully","Check logs for the companion 'Unable to abandon existing segments' warning for actual cleanup failures"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  appenderator.close();\n} catch (RuntimeException e) {\n  log.warn(e, \"appenderator close interrupted or failed; relying on kill tasks for cleanup\");\n}","preventionTips":["Don't interrupt threads that are closing appenderators; use graceful cancel flags first","Schedule periodic kill tasks so partially abandoned segments are cleaned","Alert on 'Interrupted during close()' outside of intentional shutdowns","Allow sufficient shutdown grace period for streaming tasks"],"tags":["interruption","shutdown","appenderator","streaming-ingestion"],"backgroundTag":"thread-interrupted","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}