apache/hadoop · error · FileAlreadyExistsException

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

mkDirRecursively builds the missing ancestors of f bottom-up and, while checking each level, throws FileAlreadyExistsException if an existing entry there is a file. Note a reporting quirk: the message formats the ORIGINAL path f, not the ancestor that conflicted, so the message names the requested directory while the real conflict sits at some parent. Inspect parents when it fires.

Source

Thrown at hadoop-cloud-storage-project/hadoop-cos/src/main/java/org/apache/hadoop/fs/cosn/CosNFileSystem.java:545

   *                     creating the path.
   */
  public boolean mkDirRecursively(Path f, FsPermission permission)
      throws IOException {
    Path absolutePath = makeAbsolute(f);
    List<Path> paths = new ArrayList<>();
    do {
      paths.add(absolutePath);
      absolutePath = absolutePath.getParent();
    } while (absolutePath != null);

    for (Path path : paths) {
      if (path.equals(new Path(CosNFileSystem.PATH_DELIMITER))) {
        break;
      }
      try {
        FileStatus fileStatus = getFileStatus(path);
        if (fileStatus.isFile()) {
          throw new FileAlreadyExistsException(
              String.format("Can't make directory for path: %s, "
                  + "since it is a file.", f));
        }
        if (fileStatus.isDirectory()) {
          break;
        }
      } catch (FileNotFoundException e) {
        LOG.debug("Making dir: [{}] in COS", f);

        String folderPath = pathToKey(makeAbsolute(f));
        if (!folderPath.endsWith(PATH_DELIMITER)) {
          folderPath += PATH_DELIMITER;
        }
        store.storeEmptyFile(folderPath);
      }
    }
    return true;
  }

View on GitHub (pinned to 2add963021)

Solutions

  1. Walk every ancestor of the reported path, find the entry that isFile(), and remove or relocate it.
  2. Serialize directory creation among concurrent writers or use a deterministic layout so collisions cannot occur.
  3. Retry mkdirs after cleanup.

Example fix

// before
fs.mkdirs(new Path('/etl/dt=2026/zone=cn')); // message names /etl/dt=2026/zone=cn, but conflict is at an ancestor

// after
for (Path a = new Path('/etl/dt=2026/zone=cn').getParent(); a != null; a = a.getParent()) {
  if (fs.exists(a) && fs.getFileStatus(a).isFile()) { fs.delete(a, false); }
}
fs.mkdirs(new Path('/etl/dt=2026/zone=cn'));
Defensive patterns

Strategy: validation

Validate before calling

for (Path anc = f.getParent(); anc != null && !anc.isRoot(); anc = anc.getParent()) {
  if (fs.exists(anc) && fs.getFileStatus(anc).isFile()) {
    throw new IllegalStateException('Ancestor is a file: ' + anc);
  }
}

Try / catch

try {
  fs.mkdirs(f);
} catch (FileAlreadyExistsException e) {
  // message names f, not the ancestor: walk parents to find the real file
  for (Path a = f.getParent(); a != null; a = a.getParent()) {
    if (fs.exists(a) && fs.getFileStatus(a).isFile()) { fs.delete(a, false); }
  }
  fs.mkdirs(f); // retry once
}

Prevention

When it happens

Trigger: fs.mkdirs reaching mkDirRecursively after validatePath passed, then hitting an existing file at an intermediate level; a concurrent writer creating a file at an ancestor between validatePath and the recursive walk (time-of-check/time-of-use window).

Common situations: Concurrent jobs creating conflicting layouts under the same prefix; retries after partial failures that left files at intermediate paths.

Related errors


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