elastic/elasticsearch · error · RuntimeException

Retry interrupted

Error message

Retry interrupted

What it means

Thrown by the GradleUtils retry helper when Thread.sleep during backoff between attempts is interrupted. The method restores the interrupt flag (Thread.currentThread().interrupt()) and wraps the InterruptedException in a RuntimeException. It indicates the build thread was signalled to stop while waiting to retry a flaky GradleException-throwing operation.

Source

Thrown at build-tools/src/main/java/org/elasticsearch/gradle/util/GradleUtils.java:228

     * @param retries number of retries before giving up
     * @param runnable action to run
     * */
    public static void withRetries(int retries, int gracePeriodInS, Runnable runnable) {
        int delay = gracePeriodInS;
        for (int attempt = 0; attempt <= retries; attempt++) {
            try {
                runnable.run();
                return;
            } catch (GradleException e) {
                if (attempt == retries) {
                    throw e;
                }
                System.out.println("Attempt " + (attempt + 1) + " failed, retrying in " + delay + " seconds...");
                try {
                    Thread.sleep(delay * 1000L);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException("Retry interrupted", ie);
                }
                // After the first sleep, increase delay by 20 seconds once, then grow by gracePeriodInS each retry
                if (attempt == 0) {
                    delay = gracePeriodInS + 20;
                } else {
                    delay += gracePeriodInS;
                }
            }
        }
    }
}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Avoid interrupting the build while a retried operation is in its backoff sleep.
  2. If invoking retry programmatically, ensure the calling thread's interrupt status is clear before entry.
  3. For cooperative cancellation, use a flag checked by the runnable instead of Thread.interrupt().
  4. Reduce retry count or delay so the backoff window exposed to interruption is shorter.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    GradleUtils.retry(runnable, retries, gracePeriodInS);
} catch (RuntimeException e) {
    if (Thread.currentThread().isInterrupted()) {
        // build was cancelled during backoff — shut down gracefully
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Another thread calls Thread.interrupt() while the retry loop is sleeping between attempts, e.g. a Gradle daemon shutdown, worker cancellation, or explicit build abort during a network-retry backoff.

Common situations: User cancels the build (Ctrl+C) mid-retry; Gradle worker executor cancels a long-running task; a parent process sends an interrupt to the build JVM during backoff.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/4302ec7e439514be. Report an issue: GitHub.