apache/hadoop · error · PathIOException

Can't create root path

Error message

Can't create root path

What it means

innerCreateFile() converts the target Path to an S3 object key with pathToKey(); the filesystem root (s3a://bucket/ or /) maps to the empty string, and S3 has no zero-length object key. So any create whose path resolves to the bucket root fails immediately with PathIOException on path '/' before any create flag is examined - neither overwrite, performance nor conditional options bypass it.

Source

Thrown at hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java:2100

   * If true, this method call does no IO at all.
   * @param path the file name to open
   * @param progress the progress reporter.
   * @param auditSpan audit span
   * @param options options for the file
   * @throws IOException in the event of IO related errors.
   */
  @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
  @Retries.RetryTranslated
  private FSDataOutputStream innerCreateFile(
      final Path path,
      final Progressable progress,
      final AuditSpan auditSpan,
      final CreateFileBuilder.CreateFileOptions options) throws IOException {
    auditSpan.activate();
    String key = pathToKey(path);
    if (key.isEmpty()) {
      // no matter the creation options, root cannot be written to.
      throw new PathIOException("/", "Can't create root path");
    }
    EnumSet<CreateFlag> flags = options.getFlags();

    /*
     Calculate whether to perform HEAD/LIST checks,
     and whether the conditional create option should be set.
     This seems complicated, but comes down to
     "if explicitly requested and the FS enables it, use".
     */
    // create file attributes
    boolean cCreate = options.isConditionalOverwrite();
    boolean cEtag = options.isConditionalOverwriteEtag();
    boolean createPerf = options.isPerformance();
    boolean overwrite = flags.contains(CreateFlag.OVERWRITE);

    // path attributes
    boolean magic = isUnderMagicCommitPath(path);

View on GitHub (pinned to 2add963021)

Solutions

  1. Fix the caller to pass a path with a real, non-empty last component (the object key)
  2. Validate that path.getName() / the configured filename is non-empty before calling create
  3. Log the exact path at the call site so mis-built paths surface immediately

Example fix

// before
fs.create(new Path("s3a://" + bucket + "/" + fileName));

// after: reject blank names before touching S3A
if (fileName == null || fileName.trim().isEmpty()) {
  throw new IllegalArgumentException("fileName must not be empty");
}
fs.create(new Path(new Path("s3a://" + bucket + "/"), fileName));
Defensive patterns

Strategy: validation

Validate before calling

static Path requireFileTarget(Path p) {
  if (p.isRoot() || p.toUri().getPath().equals("/")) {
    throw new IllegalArgumentException("Refusing to create at filesystem root: " + p);
  }
  return p;
}

Try / catch

If paths arrive from frameworks and cannot be pre-checked, catch PathIOException from create(), inspect getPath() and the message, and map 'Can't create root path' to an input-validation error rather than a retriable failure.

Prevention

When it happens

Trigger: fs.create(new Path("s3a://bucket/")) or create(new Path("/")); building a Path from a blank or missing filename; concatenating a parent string with a null child element so the result normalizes to the root.

Common situations: Paths assembled from unvalidated user or config input where the output filename is empty; walking getParent() one level too far; a blank output-file property making the job write to the bucket root.

Related errors


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