{"record":{"id":"0826d595a332e368","repo":"apache/hadoop","slug":"unable-to-rename-src-to-target","errorCode":null,"errorMessage":"Unable to rename \" + src + \" to \" + target","messagePattern":"Unable to rename \" \\+ src \\+ \" to \" \\+ target","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java","lineNumber":1583,"sourceCode":"   * @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.\n   */\n  public static File[] listFiles(File dir) throws IOException {\n    File[] files = dir.listFiles();\n    if(files == null) {","sourceCodeStart":1565,"sourceCodeEnd":1601,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java#L1565-L1601","documentation":"The terminal failure of replaceFile(File src, File target): after the initial src.renameTo(target) fails and the retry loop (up to 5 delete attempts of target with 1s sleeps) finishes, a second renameTo attempt that still fails throws IOException(\"Unable to rename <src> to <target>\"). On Windows this is the documented behavior when the target is open for reading/writing (see the comment block in the source); on POSIX it means cross-filesystem rename, missing permissions, or a dangling directory target.","triggerScenarios":"replaceFile on Windows with target held open by any process (antivirus scanners, indexers, your own unclosed streams); rename across mount points/filesystems; src no longer exists by the time of the second rename; target is a non-empty directory.","commonSituations":"LocalFileSystem rename during commit on Windows nodes; AV/backup software briefly locking files; renaming between /tmp and a data volume (different devices); leftover open FSDataInputStream from a read cache.","solutions":["Close all handles on src and target in YOUR process before renaming; scan for leaked streams (try-with-resources)","On Windows, exclude the directory from antivirus scanning or retry with backoff when external lockers (AV, indexer) are the culprit","Ensure src and target are on the same filesystem/device; otherwise copy-then-delete instead of rename","As a last resort, copy src to a unique temp file next to target and atomically Files.move it with ATOMIC_MOVE after deleting target"],"exampleFix":"// before\nFileUtil.replaceFile(tmpFile, finalFile);\n// IOException: Unable to rename tmpFile to finalFile\n\n// after: guaranteed-closed handles + copy fallback across filesystems\ntry (InputStream in = Files.newInputStream(tmpFile.toPath());\n     OutputStream out = Files.newOutputStream(finalTmp.toPath())) {\n  in.transferTo(out);\n}\nFiles.deleteIfExists(finalFile.toPath());\nFiles.move(finalTmp.toPath(), finalFile.toPath(),\n    StandardCopyOption.ATOMIC_MOVE);","handlingStrategy":"retry","validationCode":"// cheap pre-flight: same filesystem, writable target parent, target closeable\nif (!src.getParentFile().equals(target.getParentFile())\n    && !src.toPath().toRealPath().startsWith(target.getParentFile().toPath())) {\n  // cross-device risk: copy+delete instead of rename\n}\nif (!target.getParentFile().canWrite()) throw new IOException(\"Target parent not writable\");","typeGuard":null,"tryCatchPattern":"for (int attempt = 0; attempt < 3; attempt++) {\n  try {\n    FileUtil.replaceFile(src, target);\n    break;\n  } catch (IOException e) {\n    if (!e.getMessage().contains(\"Unable to rename\")) throw e;\n    closeLeakedHandles(target); // then wait out transient Windows locks (AV scan)\n  }\n}","preventionTips":["Keep src and target on the same filesystem/device; rename never crosses mounts","Use try-with-resources so no reader holds the target open on Windows","Exclude Hadoop data dirs from antivirus real-time scanning on Windows","Fall back to copy-then-atomic-move when rename keeps failing"],"tags":["rename-failed","windows-file-lock","cross-filesystem","file-lock","fileutil"],"backgroundTag":"file-rename-failed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}