{"record":{"id":"71266400b543f35b","repo":"apache/hadoop","slug":"rename-destination-parent-parent-is-a-file-712664","errorCode":null,"errorMessage":"rename destination parent ${parent} is a file.","messagePattern":"rename destination parent (.+?) is a file\\.","errorType":"exception","errorClass":"ParentNotDirectoryException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileSystem.java","lineNumber":1719,"sourceCode":"      }\n      // Delete the destination that is a file or an empty directory\n      if (dstStatus.isDirectory()) {\n        FileStatus[] list = listStatus(dst);\n        if (list != null && list.length != 0) {\n          throw new IOException(\n              \"rename cannot overwrite non empty destination directory \" + dst);\n        }\n      }\n      delete(dst, false);\n    } else {\n      final Path parent = dst.getParent();\n      final FileStatus parentStatus = getFileStatus(parent);\n      if (parentStatus == null) {\n        throw new FileNotFoundException(\"rename destination parent \" + parent\n            + \" not found.\");\n      }\n      if (!parentStatus.isDirectory()) {\n        throw new ParentNotDirectoryException(\"rename destination parent \" + parent\n            + \" is a file.\");\n      }\n    }\n    if (!rename(src, dst)) {\n      throw new IOException(\"rename from \" + src + \" to \" + dst + \" failed.\");\n    }\n  }\n\n  /**\n   * Truncate the file in the indicated path to the indicated size.\n   * <ul>\n   *   <li>Fails if path is a directory.</li>\n   *   <li>Fails if path does not exist.</li>\n   *   <li>Fails if path is not closed.</li>\n   *   <li>Fails if new size is greater than current size.</li>\n   * </ul>\n   * @param f The path to the file to be truncated\n   * @param newLength The size the file is to be truncated to","sourceCodeStart":1701,"sourceCodeEnd":1737,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileSystem.java#L1701-L1737","documentation":"The destination-parent check in the deprecated rename: the parent of dst exists but is a regular file, so ParentNotDirectoryException('rename destination parent parent is a file.') is thrown. Nothing can be renamed 'into' a file path.","triggerScenarios":"rename(src, a/b/c) where a/b exists as a file - the destination prefix is occupied by a file.","commonSituations":"Stale marker/output files occupying directory prefixes; layouts where a path flips between file and directory across runs; partial cleanup leaving files behind.","solutions":["Delete or relocate the file occupying the parent path (after verifying it is disposable)","Adjust the destination naming to avoid the colliding prefix","Pre-flight: assert every prefix of dst is a directory or absent"],"exampleFix":"// before\nfs.rename(src, new Path(\"/out/part-0/x\")); // /out/part-0 is a file\n\n// after\nPath dst = new Path(\"/out/part-0/x\");\nPath parent = dst.getParent();\nif (fs.exists(parent) && !fs.getFileStatus(parent).isDirectory()) {\n  fs.delete(parent, false);\n  fs.mkdirs(parent);\n}\nfs.rename(src, dst);","handlingStrategy":"validation","validationCode":"Path parent = dst.getParent();\nif (fs.exists(parent) && !fs.getFileStatus(parent).isDirectory()) {\n  throw new IllegalStateException(\"rename parent is a file: \" + parent);\n}\nfs.rename(src, dst);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep path-prefix layouts stable between runs","Assert parent type (directory or absent) before publishing","Remove stale files that occupy planned directory prefixes"],"tags":["hadoop","filesystem","rename","parent-not-directory"],"backgroundTag":"parent-not-directory","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}