apache/hadoop · error · IOException

replaceFile interrupted.

Error message

replaceFile interrupted.

What it means

replaceFile(File src, File target) first tries src.renameTo(target); on failure it retries deleting target up to 5 times with Thread.sleep(1000) between attempts. If the thread is interrupted during that sleep, the InterruptedException is caught and rethrown as IOException("replaceFile interrupted.") — without restoring the interrupt flag. The rename failure that started the retry loop is almost always Windows file locking (target open by another process/handler).

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java:1579

  /**
   * Move the src file to the name specified by target.
   * @param src the source file
   * @param target the target file
   * @exception IOException If this operation fails
   */
  public static void replaceFile(File src, File target) throws IOException {
    /* renameTo() has two limitations on Windows platform.
     * src.renameTo(target) fails if
     * 1) If target already exists OR
     * 2) If target is already open for reading/writing.
     */
    if (!src.renameTo(target)) {
      int retries = 5;
      while (target.exists() && !target.delete() && retries-- >= 0) {
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          throw new IOException("replaceFile interrupted.");
        }
      }
      if (!src.renameTo(target)) {
        throw new IOException("Unable to rename " + src +
                              " to " + target);
      }
    }
  }

  /**
   * A wrapper for {@link File#listFiles()}. This java.io API returns null
   * when a dir is not a directory or for any I/O error. Instead of having
   * null check everywhere File#listFiles() is used, we will add utility API
   * to get around this problem. For the majority of cases where we prefer
   * an IOException to be thrown.
   * @param dir directory for which listing should be performed
   * @return list of files or empty list
   * @exception IOException for invalid directory or for a bad disk.

View on GitHub (pinned to 2add963021)

Solutions

  1. Close every open handle (streams, RandomAccessFile, memory-mapped files) on src and target before calling replaceFile
  2. Retry the whole replaceFile after the interrupt source is resolved; do not assume file corruption
  3. If you interrupt intentionally, expect this message and treat it as cancellation, not data loss
  4. On Windows, prefer copying to a unique temp name and using Files.move(..., ATOMIC_MOVE) semantics with pre-closed handles

Example fix

// before (reader still open -> rename fails -> interrupted during retry)
FSDataInputStream in = localFs.open(srcPath);
FileUtil.replaceFile(src, target);
in.close();

// after
try (FSDataInputStream in = localFs.open(srcPath)) {
  // fully consume/close before rename
}
FileUtil.replaceFile(src, target);
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure no open handles on target before replacing
try (FSDataInputStream ignored = null) { /* structure code so streams close before rename */ }
if (target.exists() && target.isDirectory()) throw new IOException("Bad target");

Try / catch

try {
  FileUtil.replaceFile(src, target);
} catch (IOException e) {
  if ("replaceFile interrupted.".equals(e.getMessage())) {
    Thread.currentThread().interrupt(); // restore flag Hadoop drops
    // caller decides: retry after closing handles, or propagate as cancellation
  } else throw e;
}

Prevention

When it happens

Trigger: replaceFile on Windows while the target is held open by a reader (e.g., an unclosed FSDataInputStream/RandomAccessFile); the copying thread is cancelled (ExecutorService.shutdownNow, timeout) exactly while it sleeps between delete retries.

Common situations: LocalFileSystem rename over an open file on Windows nodes; job cancellation during checkpoint/rename commit; test frameworks shutting down thread pools mid-operation.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/6142cc3114b0328f. Report an issue: GitHub.