apache/hadoop · warning · RenameFailedException

source is root directory

Error message

source is root directory

What it means

initiateRename() maps src to an S3 key; an empty srcKey means the source is the bucket root (s3a://bucket/), which cannot be renamed. RenameFailedException 'source is root directory' is thrown; rename() catches it, logs at INFO and returns the exception's exit code (false here), so callers observe rename(...) returning false rather than an IOException.

Source

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

   * @param src qualified path to be renamed
   * @param dst qualified path after rename
   * @return the source and (possibly null) destination status entries.
   * @throws RenameFailedException if some criteria for a state changing
   * rename was not met. This means work didn't happen; it's not something
   * which is reported upstream to the FileSystem APIs, for which the semantics
   * of "false" are pretty vague.
   * @throws FileNotFoundException there's no source file.
   * @throws IOException on IO failure.
   */
  @Retries.RetryTranslated
  private Pair<S3AFileStatus, S3AFileStatus> initiateRename(
      final Path src,
      final Path dst) throws IOException {
    String srcKey = pathToKey(src);
    String dstKey = pathToKey(dst);

    if (srcKey.isEmpty()) {
      throw new RenameFailedException(src, dst, "source is root directory");
    }
    if (dstKey.isEmpty()) {
      throw new RenameFailedException(src, dst, "dest is root directory");
    }

    // get the source file status; this raises a FNFE if there is no source
    // file.
    S3AFileStatus srcStatus = innerGetFileStatus(src, true,
        StatusProbeEnum.ALL);

    if (srcKey.equals(dstKey)) {
      LOG.debug("rename: src and dest refer to the same file or directory: {}",
          dst);
      throw new RenameFailedException(src, dst,
          "source and dest refer to the same file or directory")
          .withExitCode(srcStatus.isFile());
    }

View on GitHub (pinned to 2add963021)

Solutions

  1. Fix the caller to rename a non-root source path
  2. To relocate everything under root, list the root and rename each child individually
  3. Guard with src.isRoot() before calling rename and fail with a clear message

Example fix

// before
boolean ok = fs.rename(new Path("/"), dst);

// after: refuse root sources up front
if (src.isRoot()) {
  throw new IllegalArgumentException("cannot rename the bucket root: " + src);
}
boolean ok = fs.rename(src, dst);
Defensive patterns

Strategy: validation

Validate before calling

if (src.isRoot()) {
  throw new IllegalArgumentException("cannot rename bucket root as source");
}

Prevention

When it happens

Trigger: rename(new Path("/"), dst) or any src that qualifies to the bucket root; src computed via getParent() on a top-level file.

Common situations: Directory-walking code that ends up renaming a parent; attempts to 'move the whole bucket' by renaming its root; off-by-one path arithmetic landing on root.

Related errors


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