{"record":{"id":"3820ddbb6de22af2","repo":"apache/druid","slug":"thread-interrupted-while-flushing","errorCode":null,"errorMessage":"Thread Interrupted while flushing","messagePattern":"Thread Interrupted while flushing","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"warning","filePath":"processing/src/main/java/org/apache/druid/java/util/emitter/core/HttpPostEmitter.java","lineNumber":434,"sourceCode":"  {\n    if (batch == null) {\n      return;\n    }\n    batch.seal();\n    try {\n      // This check doesn't always awaits for this exact batch to be emitted, because another batch could be dropped\n      // from the queue ahead of this one, in limitBuffersToEmitSize(). But there is no better way currently to wait for\n      // the exact batch, and it's not that important.\n      emittedBatchCounter.awaitCount(batch.batchNumber, config.getFlushTimeOut(), TimeUnit.MILLISECONDS);\n    }\n    catch (TimeoutException e) {\n      String message = StringUtils.format(\"Timed out after [%d] millis during flushing\", config.getFlushTimeOut());\n      throw new IOException(message, e);\n    }\n    catch (InterruptedException e) {\n      log.debug(\"Thread Interrupted\");\n      Thread.currentThread().interrupt();\n      throw new IOException(\"Thread Interrupted while flushing\", e);\n    }\n  }\n\n  @Override\n  @LifecycleStop\n  public void close() throws IOException\n  {\n    synchronized (startLock) {\n      if (running) {\n        running = false;\n        Object lastBatch = concurrentBatch.getAndSet(null);\n        if (lastBatch instanceof Batch) {\n          flush((Batch) lastBatch);\n        }\n        emittingThread.shuttingDown = true;\n        // EmittingThread is interrupted after the last batch is flushed.\n        emittingThread.interrupt();\n      }","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/java/util/emitter/core/HttpPostEmitter.java#L416-L452","documentation":"flush() blocks on emittedBatchCounter.awaitCount, which can throw InterruptedException if the calling thread is interrupted while waiting for the batch to be emitted. The code re-interrupts the thread and wraps the cause in IOException('Thread Interrupted while flushing'). It signals the flush did not complete because the caller was interrupted, not because of a network problem.","triggerScenarios":"A thread calling flush() or close() is interrupted (Thread.interrupt()) mid-wait — e.g. Druid Lifecycle stop, executor shutdownNow(), or task cancellation during shutdown.","commonSituations":"JVM shutdown hooks or supervisors interrupting worker threads while they flush telemetry; ScheduledExecutorService shutdownNow() cancelling a periodic flush; Druid task kill interrupting peon threads.","solutions":["Avoid interrupting threads that are flushing; complete flushes before shutdownNow().","Catch IOException and check the cause is InterruptedException; restore interrupt status and proceed with shutdown.","Use close() in a non-interruptible shutdown phase, or give it a dedicated thread.","Reduce flush wait time (flushTimeOut) so flushes finish before interruption deadlines."],"exampleFix":"// before\nexecutor.shutdownNow(); // interrupts in-flight flush\n// after\nemitter.close();\nexecutor.shutdownNow();","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  emitter.flush();\n} catch (IOException e) {\n  if (e.getCause() instanceof InterruptedException) {\n    Thread.currentThread().interrupt();\n    log.debug(\"Flush interrupted; deferring to shutdown\");\n  }\n}","preventionTips":["Don't call shutdownNow() on threads performing flush","Run close()/flush() on a dedicated, non-interrupted shutdown thread","Complete flushes before cancelling scheduled flush tasks"],"tags":["interrupt","flush","shutdown"],"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"}