apache/hadoop · error · FileAlreadyExistsException

Can't make directory for path

Error message

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

What it means

When innerMkdirs cannot find the requested directory, it walks UP the ancestor chain (fPart = path.getParent(); do/while to root) and stats each parent. If any ancestor exists as a FILE, it throws FileAlreadyExistsException("Can't make directory for path '<ancestor>' since it is a file.") — you cannot create a directory underneath an object key. Note the reported path is the offending ANCESTOR (fPart), not the path you passed, which often confuses readers of the message.

Solutions

  1. Identify the file named in the message, confirm it is disposable, then delete or rename it (fs.rename to a '_files/' prefix or delete).
  2. Restructure the layout so every path component used as a directory is only ever a directory/prefix.
  3. Add a layout lint at job start: for each mkdirs target, verify no ancestor exists as a file (cheap getFileStatus walk) and fail with an actionable message.
  4. If the file must stay, move your data tree to a sibling prefix that has no file ancestors.

Example fix

// before
fs.mkdirs(new Path("obs://b/a/b/c"));
// throws: Can't make directory for path 'obs://b/a' since it is a file.

// after
Path a = new Path("obs://b/a");
if (fs.getFileStatus(a).isFile()) {
  fs.rename(a, new Path("obs://b/_files/a")); // relocate conflicting object
}
fs.mkdirs(new Path("obs://b/a/b/c"));
Defensive patterns

Strategy: validation

Validate before calling

static void ensureAncestorsAreDirs(FileSystem fs, Path p) throws IOException {
  for (Path a = p.getParent(); a != null && !a.isRoot(); a = a.getParent()) {
    if (fs.exists(a) && fs.getFileStatus(a).isFile()) {
      throw new FileAlreadyExistsException("ancestor is a file: " + a);
    }
  }
  fs.mkdirs(p);
}

Try / catch

try {
  fs.mkdirs(path);
} catch (FileAlreadyExistsException e) {
  if (String.valueOf(e.getMessage()).contains("since it is a file")) {
    // message names the offending ANCESTOR, not 'path'
    Path offender = extractQuotedPath(e.getMessage());
    throw new LayoutConflictException("file blocks directory tree at " + offender, e);
  }
  throw e;
}

Prevention

When it happens

Trigger: mkdirs('obs://b/a/b/c') when object 'obs://b/a' exists as a file: the walk hits a, sees isFile(), throws naming 'a'. Typical with key layouts where 'a' was written as a plain object and later code assumes it is a directory; flatten-then-hierarchical schema changes; upstream producers writing marker files at directory prefixes.

Common situations: Schema evolution adding partition levels under a formerly leaf key; different writers disagreeing whether a prefix is a file or dir; manual uploads of files named like directories; migration from another FS where such layout was legal.

Related errors


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

Appendix: source

Thrown at hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSCommonUtils.java:731

    FileStatus fileStatus;
    try {
      fileStatus = owner.getFileStatus(path);

      if (fileStatus.isDirectory()) {
        return true;
      } else {
        throw new FileAlreadyExistsException("Path is a file: " + path);
      }
    } catch (FileNotFoundException e) {
      Path fPart = path.getParent();
      do {
        try {
          fileStatus = owner.getFileStatus(fPart);
          if (fileStatus.isDirectory()) {
            break;
          }
          if (fileStatus.isFile()) {
            throw new FileAlreadyExistsException(
                String.format("Can't make directory for path '%s'"
                    + " since it is a file.", fPart));
          }
        } catch (FileNotFoundException fnfe) {
          LOG.debug("file {} not fount, but ignore.", path);
        }
        fPart = fPart.getParent();
      } while (fPart != null);

      String key = pathToKey(owner, path);
      if (owner.isFsBucket()) {
        OBSPosixBucketUtils.fsCreateFolder(owner, key);
      } else {
        OBSObjectBucketUtils.createFakeDirectory(owner, key);
      }
      return true;
    }
  }

View on GitHub (pinned to 2add963021)