{"record":{"id":"2b9dfddbe552a987","repo":"apache/flink","slug":"operation-interrupted","errorCode":null,"errorMessage":"operation interrupted","messagePattern":"operation interrupted","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"warning","filePath":"flink-core/src/main/java/org/apache/flink/util/FileUtils.java","lineNumber":410,"sourceCode":"    // or  make this locking more fine grained, for example  on directory path prefixes\n    private static void guardIfWindows(ThrowingConsumer<File, IOException> toRun, File file)\n            throws IOException {\n        synchronized (DELETE_LOCK) {\n            for (int attempt = 1; attempt <= 10; attempt++) {\n                try {\n                    toRun.accept(file);\n                    break;\n                } catch (AccessDeniedException e) {\n                    // ah, windows...\n                }\n\n                // briefly wait and fall through the loop\n                try {\n                    Thread.sleep(1);\n                } catch (InterruptedException e) {\n                    // restore the interruption flag and error out of the method\n                    Thread.currentThread().interrupt();\n                    throw new IOException(\"operation interrupted\");\n                }\n            }\n        }\n    }\n\n    // Guard Mac for the same reason we guard windows. Refer to guardIfWindows for details.\n    // The difference to guardIfWindows is that we don't swallow the AccessDeniedException because\n    // doing that would lead to wrong behaviour.\n    private static void guardIfMac(ThrowingConsumer<File, IOException> toRun, File file)\n            throws IOException {\n        synchronized (DELETE_LOCK) {\n            toRun.accept(file);\n        }\n    }\n\n    /**\n     * Copies all files from source to target and sets executable flag. Paths might be on different\n     * systems.","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/util/FileUtils.java#L392-L428","documentation":"guardIfWindows retries file operations on Windows inside a loop because Windows throws AccessDeniedException while a file is still mmap'ed or held open by another process (a known JVM/OS quirk). Between retries it sleeps 1ms; if that sleep is interrupted, the method restores the thread's interrupt flag and throws IOException(\"operation interrupted\"). It is a control-flow error: the deletion/delete operation was aborted because the calling thread was interrupted, not because of an I/O failure.","triggerScenarios":"Running on Windows (or macOS with the analogous guard) and interrupting the thread executing FileUtils.deleteFileOrDirectory/deleteDirectory — e.g. cancelling a job, shutting down an executor, or a timeout-based Future cancellation while local file cleanup is in progress.","commonSituations":"Local Flink runs on Windows developers' machines where cleanup tasks run in a thread pool that gets shutdownNow() (which interrupts workers) during job cancellation or JVM shutdown hooks.","solutions":["Let the interrupted thread exit gracefully: since the interrupt flag is already restored, catch the IOException, check Thread.currentThread().isInterrupted(), and skip re-attempting the delete","Avoid interrupting threads that perform file cleanup — use shutdown() instead of shutdownNow(), or run cleanup on a non-interruptible path","Retry the deletion once on a fresh (non-interrupted) thread if the cleanup must complete"],"exampleFix":"// before\nexecutor.shutdownNow(); // interrupts cleanup thread -> IOException(\"operation interrupted\")\n\n// after\nexecutor.shutdown();\nexecutor.awaitTermination(30, TimeUnit.SECONDS);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    FileUtils.deleteFileOrDirectory(file);\n} catch (IOException e) {\n    if (Thread.currentThread().isInterrupted()) { /* aborted by cancel: stop cleanup */ return; }\n    throw e;\n}","preventionTips":["Never shutdownNow() executors that own file-cleanup tasks; use shutdown + awaitTermination","Keep cancellation-aware cleanup in threads designed to be interrupted","Remember the interrupt flag is already restored by the thrower — do not interrupt again blindly"],"tags":["filesystem","windows","interruption","concurrency"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}