{"record":{"id":"e690ecf664c173b0","repo":"apache/druid","slug":"current-thread-is-interrupted-after-s-tries","errorCode":null,"errorMessage":"Current thread is interrupted after [%s] tries","messagePattern":"Current thread is interrupted after \\[(.+?)\\] tries","errorType":"exception","errorClass":"RE","httpStatus":null,"severity":"warning","filePath":"processing/src/main/java/org/apache/druid/java/util/common/RetryUtils.java","lineNumber":148,"sourceCode":"      }\n      catch (Throwable e) {\n        if (cleanupAfterFailure != null) {\n          cleanupAfterFailure.cleanup();\n        }\n        if (nTry < maxTries && shouldRetry.apply(e)) {\n          if (!skipSleep) {\n            awaitNextRetry(e, messageOnRetry, nTry, maxRetries, nTry <= quietTries);\n          }\n        } else {\n          Throwables.propagateIfInstanceOf(e, Exception.class);\n          throw new RuntimeException(e);\n        }\n      }\n    }\n    if (cleanupAfterFailure != null) {\n      cleanupAfterFailure.cleanup();\n    }\n    throw new RE(\"Current thread is interrupted after [%s] tries\", nTry);\n  }\n\n  public static <T> T retry(final Task<T> f, Predicate<Throwable> shouldRetry, final int maxTries) throws Exception\n  {\n    return retry(f, shouldRetry, 0, maxTries);\n  }\n\n  public static <T> T retry(\n      final Task<T> f,\n      final Predicate<Throwable> shouldRetry,\n      final int quietTries,\n      final int maxTries\n  ) throws Exception\n  {\n    return retry(f, shouldRetry, quietTries, maxTries, null, null);\n  }\n\n  public static <T> T retry(","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/java/util/common/RetryUtils.java#L130-L166","documentation":"RetryUtils.retry(...) stops retrying immediately when the current thread is interrupted. After running cleanup and exhausting that check, it throws a RejectedExecutionException (RE) reporting the number of tries at which the interruption was observed. This surfaces the thread's interrupt status rather than masking it with further retries.","triggerScenarios":"The calling thread's interrupt flag is set while inside RetryUtils.retry — e.g. a Druid query is cancelled/times out and its task thread is interrupted, or shutdown interrupts a worker thread mid-retry.","commonSituations":"Query cancellation in Druid (cancellation or timeout interrupts task threads that are retrying an HTTP fetch or segment load); service shutdown interrupting background retry loops.","solutions":["Let the thread terminate: don't swallow this — treat it as cancellation and unwind the operation.","Check Thread.currentThread().isInterrupted() before entering long retry loops and abort early.","Fix whatever is interrupting the thread prematurely (cancellation logic, executor shutdown timing, timeouts too short).","If interruption is expected and safe to continue (rare), clear and re-check policy explicitly — usually not recommended."],"exampleFix":"// before\nT result = RetryUtils.retry(task, shouldRetry, 5);\n// after\nif (!Thread.currentThread().isInterrupted()) {\n  T result = RetryUtils.retry(task, shouldRetry, 5);\n} else {\n  throw new InterruptedException(\"Cancelled before retrying\");\n}","handlingStrategy":"try-catch","validationCode":"if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(\"Interrupted before retry\"); }","typeGuard":null,"tryCatchPattern":"try {\n  result = RetryUtils.retry(task, shouldRetry, maxTries);\n} catch (RejectedExecutionException | InterruptedException e) {\n  Thread.currentThread().interrupt(); // preserve status and unwind\n  throw new CancellationException(\"Operation cancelled\");\n}","preventionTips":["Check isInterrupted() before starting long retry loops","Never swallow InterruptedException without restoring the interrupt flag","Match executor/timeout shutdown behavior with retry expectations"],"tags":["retry","thread-interrupt","cancellation"],"backgroundTag":"request-timeout","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"}