{"record":{"id":"aec790598879d976","repo":"apache/hadoop","slug":"rename-destination-parent-parent-is-a-file","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/AbstractFileSystem.java","lineNumber":892,"sourceCode":"      }\n      if (!overwrite) {\n        throw new FileAlreadyExistsException(\"Rename destination \" + dst\n            + \" already exists.\");\n      }\n      // Delete the destination that is a file or an empty directory\n      if (dstStatus.isDirectory()) {\n        RemoteIterator<FileStatus> list = listStatusIterator(dst);\n        if (list != null && list.hasNext()) {\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.isFile()) {\n        throw new ParentNotDirectoryException(\"Rename destination parent \"\n            + parent + \" is a file.\");\n      }\n    }\n    renameInternal(src, dst);\n  }\n  \n  /**\n   * Returns true if the file system supports symlinks, false otherwise.\n   * @return true if filesystem supports symlinks\n   */\n  public boolean supportsSymlinks() {\n    return false;\n  }\n  \n  /**\n   * The specification of this method matches that of  \n   * {@link FileContext#createSymlink(Path, Path, boolean)};\n   *","sourceCodeStart":874,"sourceCodeEnd":910,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/AbstractFileSystem.java#L874-L910","documentation":"When the destination does not exist, renameInternal validates its parent: if getFileStatus(dst.getParent()) resolves to a regular file, the destination cannot be created beneath it and ParentNotDirectoryException is thrown before renameInternal runs. This is the same ENOTDIR-style failure the HDFS NameNode reports, surfaced client-side by FileContext.","triggerScenarios":"fc.rename(f, new Path(\"/out/part-0/data\")) when /out/part-0 is an existing file; dynamically built paths (date/part keys) whose parent component collides with a file written by an earlier flat layout.","commonSituations":"Output layouts that append extra path components after an upstream schema change; a previous run writing a file exactly where the next run expects a directory; committer working-dir misconfiguration in MapReduce/Spark jobs.","solutions":["Remove or relocate the conflicting parent file, then fc.mkdir(parent, permission, true) before renaming","Adjust destination naming so every parent component is always a directory","Validate dst.getParent() with getFileStatus at job startup and fail fast with a clear message"],"exampleFix":"// before\nfc.rename(src, new Path(\"/out/part-0/data\")); // /out/part-0 is a file\n\n// after\nPath parent = dst.getParent();\nif (fc.util().exists(parent) && fc.getFileStatus(parent).isFile()) {\n  fc.delete(parent, false);\n  fc.mkdir(parent, FsPermission.getDirDefault(), true);\n}\nfc.rename(src, dst);","handlingStrategy":"validation","validationCode":"Path parent = dst.getParent();\nif (fc.util().exists(parent)) {\n  FileStatus ps = fc.getFileStatus(parent);\n  if (!ps.isDirectory()) {\n    throw new IllegalStateException(\"Rename parent is a file: \" + parent);\n  }\n} else {\n  fc.mkdir(parent, FsPermission.getDirDefault(), true);\n}","typeGuard":null,"tryCatchPattern":"catch (ParentNotDirectoryException e) { /* remove/relocate the conflicting parent file, mkdir parent, retry */ }","preventionTips":["Validate dst.getParent() with getFileStatus before renames into dynamically built paths","Ensure output layout changes clean up old flat files that now sit where directories are expected","mkdirs destination parents as part of job setup rather than assuming they exist"],"tags":["rename","parentnotdirectory","path-layout","filecontext","hadoop-fs"],"backgroundTag":"parent-not-directory","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}