{"record":{"id":"58de5b27004336e8","repo":"elastic/elasticsearch","slug":"interrupted-while-retrying-download-from","errorCode":null,"errorMessage":"Interrupted while retrying download from: {}","messagePattern":"Interrupted while retrying download from: (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/util/HttpUtils.java","lineNumber":47,"sourceCode":"    }\n\n    public static byte[] readHttpBytesWithRetry(String url, int maxAttempts, long baseBackoffMillis, Sleeper sleeper) throws IOException {\n        if (maxAttempts <= 0) {\n            throw new IllegalArgumentException(\"maxAttempts must be >= 1 but was [\" + maxAttempts + \"]\");\n        }\n        if (baseBackoffMillis < 0) {\n            throw new IllegalArgumentException(\"baseBackoffMillis must be >= 0 but was [\" + baseBackoffMillis + \"]\");\n        }\n\n        IOException lastException = null;\n        for (int attempt = 1; attempt <= maxAttempts; attempt++) {\n            if (attempt > 1 && baseBackoffMillis > 0) {\n                long backoff = baseBackoffMillis * (attempt - 1);\n                try {\n                    sleeper.sleep(backoff);\n                } catch (InterruptedException e) {\n                    Thread.currentThread().interrupt();\n                    throw new IOException(\"Interrupted while retrying download from: \" + url, e);\n                }\n            }\n\n            try (InputStream in = URI.create(url).toURL().openStream()) {\n                return in.readAllBytes();\n            } catch (IOException e) {\n                lastException = e;\n            }\n        }\n        assert lastException != null;\n        throw lastException;\n    }\n}\n","sourceCodeStart":29,"sourceCodeEnd":61,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/util/HttpUtils.java#L29-L61","documentation":"Raised by readHttpBytesWithRetry when the thread is interrupted during the inter-attempt backoff sleep. The method re-asserts the interrupt status (Thread.currentThread().interrupt()) and wraps the InterruptedException in an IOException so the checked-interrupt contract is preserved while still failing the download. The offending URL is included.","triggerScenarios":"A Gradle build task or worker thread calling readHttpBytesWithRetry is cancelled (e.g. build aborted, executor shutdown) mid-backoff between HTTP attempts; a test injects an interrupt to abort a hanging download.","commonSituations":"User cancels a long-running Gradle download task; a worker thread pool is shut down during resource fetching; CI timeout interrupts the build while it retries a flaky URL.","solutions":["If the interrupt was unintentional, find the source of Thread.interrupt() / executor shutdown and avoid cancelling the download prematurely.","Treat this as a normal abort: let the IOException propagate and ensure callers release partial resources.","If downloads must be cancellable, design an explicit cancellation flag instead of relying on thread interruption."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    bytes = HttpUtils.readHttpBytesWithRetry(url);\n} catch (IOException e) {\n    if (Thread.currentThread().isInterrupted()) {\n        // download aborted via interrupt; release partial resources, re-flag interrupt\n        Thread.currentThread().interrupt();\n        throw e;\n    }\n    // genuine network failure - retry/fallback as needed\n}","preventionTips":["Don't interrupt worker threads that are mid-download unless you intend to abort.","Use a cooperative cancellation flag instead of Thread.interrupt() for cancellable downloads.","Always restore the interrupt flag in catch blocks that handle InterruptedException/IOException-from-interrupt."],"tags":["network","concurrency","http","build","interruption"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}