apache/hadoop · error · FileAlreadyExistsException

Can't make directory for path '%s', it is a file.

Error message

Can't make directory for path '%s', it is a file.

What it means

validatePath() walks up the ancestor chain before mkdirs and throws FileAlreadyExistsException when any ancestor of the directory being created exists as a file: a directory cannot be created under a path occupied by an object. The message names the offending ancestor, not the requested directory.

Source

Thrown at hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/RawFileSystem.java:489

      }
    } catch (FileNotFoundException e) {
      Path dir = makeQualified(path);
      validatePath(dir);
      fsOps.mkdirs(dir);
    }
    return true;
  }

  private void validatePath(Path path) throws IOException {
    Path parent = path.getParent();
    do {
      try {
        FileStatus fileStatus = innerFileStatus(parent);
        if (fileStatus.isDirectory()) {
          // If path exists and a directory, exit
          break;
        } else {
          throw new FileAlreadyExistsException(String.format("Can't make directory for path '%s',"
                  + " it is a file.", parent));
        }
      } catch (FileNotFoundException ignored) {
      }
      parent = parent.getParent();
    } while (parent != null);
  }

  @Override
  public FileStatus getFileStatus(Path path) throws IOException {
    try {
      return innerFileStatus(path);
    } catch (ParentNotDirectoryException e) {
      // Treat ParentNotDirectoryException as FileNotFoundException for the case that check whether
      // path exist or not.
      throw new FileNotFoundException(e.getMessage());
    }
  }

View on GitHub (pinned to 2add963021)

Solutions

  1. Rename or delete the file occupying the ancestor path, then retry mkdirs
  2. Redesign the key layout so files never occupy prefixes of directory paths (object stores require prefix/file disjointness)
  3. Pre-check the ancestor chain and emit a clear error naming the blocking file

Example fix

// before
fs.mkdirs(new Path("/reports/2024/day-1")); // '/reports' is a file object -> exception

// after: keep files and directory prefixes disjoint
fs.delete(new Path("/reports"), false); // remove the blocking file
fs.mkdirs(new Path("/reports/2024/day-1"));
Defensive patterns

Strategy: validation

Validate before calling

static Path fileAncestor(FileSystem fs, Path dir) throws IOException {
  for (Path p = dir.getParent(); p != null; p = p.getParent()) {
    if (fs.exists(p) && !fs.getFileStatus(p).isDirectory()) return p;
  }
  return null;
}
Path blocker = fileAncestor(fs, dir);
if (blocker != null) throw new IllegalStateException("ancestor is a file: " + blocker);

Try / catch

try { fs.mkdirs(dir); }
catch (FileAlreadyExistsException e) {
  // message names the ancestor file: parse or walk parents to relocate it
}

Prevention

When it happens

Trigger: fs.mkdirs('/a/b/c') where '/a' or '/a/b' exists as a file object; the loop climbs parent.getParent() until it finds an existing non-directory or reaches the root.

Common situations: Deep partition paths whose prefix was previously written as a flat file ('user.csv' vs 'user.csv/day=1/'); key-layout migrations that introduce hierarchy below existing objects; date-partitioned outputs that collide with file names chosen earlier.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/a6e040653caddef0. Report an issue: GitHub.