apache/flink · warning · IOException
operation interrupted
Error message
operation interrupted
What it means
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.
Source
Thrown at flink-core/src/main/java/org/apache/flink/util/FileUtils.java:410
// or make this locking more fine grained, for example on directory path prefixes
private static void guardIfWindows(ThrowingConsumer<File, IOException> toRun, File file)
throws IOException {
synchronized (DELETE_LOCK) {
for (int attempt = 1; attempt <= 10; attempt++) {
try {
toRun.accept(file);
break;
} catch (AccessDeniedException e) {
// ah, windows...
}
// briefly wait and fall through the loop
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// restore the interruption flag and error out of the method
Thread.currentThread().interrupt();
throw new IOException("operation interrupted");
}
}
}
}
// Guard Mac for the same reason we guard windows. Refer to guardIfWindows for details.
// The difference to guardIfWindows is that we don't swallow the AccessDeniedException because
// doing that would lead to wrong behaviour.
private static void guardIfMac(ThrowingConsumer<File, IOException> toRun, File file)
throws IOException {
synchronized (DELETE_LOCK) {
toRun.accept(file);
}
}
/**
* Copies all files from source to target and sets executable flag. Paths might be on different
* systems.View on GitHub (pinned to 2f3c205e92)
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
Example fix
// before
executor.shutdownNow(); // interrupts cleanup thread -> IOException("operation interrupted")
// after
executor.shutdown();
executor.awaitTermination(30, TimeUnit.SECONDS); Defensive patterns
Strategy: try-catch
Try / catch
try {
FileUtils.deleteFileOrDirectory(file);
} catch (IOException e) {
if (Thread.currentThread().isInterrupted()) { /* aborted by cancel: stop cleanup */ return; }
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Error while getting the file registered under '${name}' from
- Interrupted when untarring file {inFilePath}
- Failed to create directory {outputFile}
- {directory}
- Interrupted while uploading object for key: {}
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/2b9dfddbe552a987.
Report an issue: GitHub.