apache/hadoop · error · ParentNotDirectoryException
Can't make directory for path %s since it is a file.
Error message
Can't make directory for path %s since it is a file.
What it means
mkdirs() first checks whether the target exists; if it exists and is a regular file, creating a directory there is impossible and ParentNotDirectoryException is thrown — the standard Hadoop signal for 'a path component that must be a directory is a file'. Here the conflict is the target path itself.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java:606
* the overhead of opening/closing a TCP connection.
*/
private boolean mkdirs(FTPClient client, Path file, FsPermission permission)
throws IOException {
boolean created = true;
Path workDir = new Path(client.printWorkingDirectory());
Path absolute = makeAbsolute(workDir, file);
String pathName = absolute.getName();
if (!exists(client, absolute)) {
Path parent = absolute.getParent();
created = (parent == null || mkdirs(client, parent, FsPermission
.getDirDefault()));
if (created) {
String parentDir = parent.toUri().getPath();
client.changeWorkingDirectory(parentDir);
created = created && client.makeDirectory(pathName);
}
} else if (isFile(client, absolute)) {
throw new ParentNotDirectoryException(String.format(
"Can't make directory for path %s since it is a file.", absolute));
}
return created;
}
/**
* Convenience method, so that we don't open a new connection when using this
* method from within another method. Otherwise every API invocation incurs
* the overhead of opening/closing a TCP connection.
*/
private boolean isFile(FTPClient client, Path file) {
try {
return getFileStatus(client, file).isFile();
} catch (FileNotFoundException e) {
return false; // file does not exist
} catch (IOException ioe) {
throw new FTPException("File check failed", ioe);
}View on GitHub (pinned to 2add963021)
Solutions
- Remove the conflicting file first: if (fs.exists(p) && fs.getFileStatus(p).isFile()) fs.delete(p, false)
- Use distinct paths for file and directory artifacts instead of reusing the same string
- Catch ParentNotDirectoryException to fail with a message naming the conflicting path
Example fix
// before
fs.mkdirs(new Path("/data/out")); // /data/out exists as a file
// ParentNotDirectoryException
// after
Path p = new Path("/data/out");
if (fs.exists(p) && fs.getFileStatus(p).isFile()) {
fs.delete(p, false);
}
fs.mkdirs(p); Defensive patterns
Strategy: validation
Validate before calling
if (fs.exists(dir) && fs.getFileStatus(dir).isFile()) {
fs.delete(dir, false); // clear the file conflicting with the directory path
}
boolean ok = fs.mkdirs(dir); Type guard
static boolean isFreeForDirectory(FileSystem fs, Path p) throws IOException {
return !fs.exists(p) || fs.getFileStatus(p).isDirectory();
} Try / catch
try {
fs.mkdirs(dir);
} catch (ParentNotDirectoryException e) {
// a file occupies the path: surface which path conflicted instead of a generic failure
throw new IOException("Path conflicts with an existing file: " + dir, e);
} Prevention
- Never reuse one path string for both a file and a directory artifact
- Check exists() + isFile() before mkdirs when paths come from configuration
- Clean stale artifacts from previous runs during job setup
When it happens
Trigger: fs.mkdirs(path) where path already exists as a file; checkpoint/restart directories whose path was previously an output file; create-then-mkdirs ordering bugs in job setup.
Common situations: Reusing one path for different artifact types between runs; logic changes that turn a file path into a directory path; incomplete cleanup after a failed run leaves a file where a directory is now expected.
Related errors
- Parent path is not a directory: " + parent
- create(): Mkdirs failed to create: {parent}
- Not a directory: {}
- Can't make directory for path '%s', it is a file.
- Path is a file: {}
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/5acaaf464fdda424.
Report an issue: GitHub.