{"record":{"id":"6142cc3114b0328f","repo":"apache/hadoop","slug":"replacefile-interrupted","errorCode":null,"errorMessage":"replaceFile interrupted.","messagePattern":"replaceFile interrupted\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java","lineNumber":1579,"sourceCode":"  /**\n   * Move the src file to the name specified by target.\n   * @param src the source file\n   * @param target the target file\n   * @exception IOException If this operation fails\n   */\n  public static void replaceFile(File src, File target) throws IOException {\n    /* renameTo() has two limitations on Windows platform.\n     * src.renameTo(target) fails if\n     * 1) If target already exists OR\n     * 2) If target is already open for reading/writing.\n     */\n    if (!src.renameTo(target)) {\n      int retries = 5;\n      while (target.exists() && !target.delete() && retries-- >= 0) {\n        try {\n          Thread.sleep(1000);\n        } catch (InterruptedException e) {\n          throw new IOException(\"replaceFile interrupted.\");\n        }\n      }\n      if (!src.renameTo(target)) {\n        throw new IOException(\"Unable to rename \" + src +\n                              \" to \" + target);\n      }\n    }\n  }\n\n  /**\n   * A wrapper for {@link File#listFiles()}. This java.io API returns null\n   * when a dir is not a directory or for any I/O error. Instead of having\n   * null check everywhere File#listFiles() is used, we will add utility API\n   * to get around this problem. For the majority of cases where we prefer\n   * an IOException to be thrown.\n   * @param dir directory for which listing should be performed\n   * @return list of files or empty list\n   * @exception IOException for invalid directory or for a bad disk.","sourceCodeStart":1561,"sourceCodeEnd":1597,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java#L1561-L1597","documentation":"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).","triggerScenarios":"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.","commonSituations":"LocalFileSystem rename over an open file on Windows nodes; job cancellation during checkpoint/rename commit; test frameworks shutting down thread pools mid-operation.","solutions":["Close every open handle (streams, RandomAccessFile, memory-mapped files) on src and target before calling replaceFile","Retry the whole replaceFile after the interrupt source is resolved; do not assume file corruption","If you interrupt intentionally, expect this message and treat it as cancellation, not data loss","On Windows, prefer copying to a unique temp name and using Files.move(..., ATOMIC_MOVE) semantics with pre-closed handles"],"exampleFix":"// before (reader still open -> rename fails -> interrupted during retry)\nFSDataInputStream in = localFs.open(srcPath);\nFileUtil.replaceFile(src, target);\nin.close();\n\n// after\ntry (FSDataInputStream in = localFs.open(srcPath)) {\n  // fully consume/close before rename\n}\nFileUtil.replaceFile(src, target);","handlingStrategy":"try-catch","validationCode":"// ensure no open handles on target before replacing\ntry (FSDataInputStream ignored = null) { /* structure code so streams close before rename */ }\nif (target.exists() && target.isDirectory()) throw new IOException(\"Bad target\");","typeGuard":null,"tryCatchPattern":"try {\n  FileUtil.replaceFile(src, target);\n} catch (IOException e) {\n  if (\"replaceFile interrupted.\".equals(e.getMessage())) {\n    Thread.currentThread().interrupt(); // restore flag Hadoop drops\n    // caller decides: retry after closing handles, or propagate as cancellation\n  } else throw e;\n}","preventionTips":["Close every stream/handle on src and target before replaceFile (try-with-resources)","Do not shutdownNow() executors mid-rename; let the operation finish or design cancellation checkpoints","On Windows, delay AV/indexer scanning of the target directory"],"tags":["rename","windows-file-lock","interrupted","concurrency","fileutil"],"backgroundTag":"thread-interrupted","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}