apache/hadoop · error · IOException

{} is root directory

Error message

{} is root directory

What it means

renameBasedOnObject converts the source Path to an object key; the bucket root converts to the empty key. An empty srcKey means the caller asked to rename the bucket itself, which object storage cannot express, so the code logs 'rename: src [...] is root directory' and throws IOException('<src> is root directory') before any status lookup.

Source

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

   * @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.
   * @throws ObsException          on failures inside the OBS SDK
   */
  static boolean renameBasedOnObject(final OBSFileSystem owner,
      final Path src, final Path dst) throws RenameFailedException,
      FileNotFoundException, IOException,
      ObsException {
    String srcKey = OBSCommonUtils.pathToKey(owner, src);
    String dstKey = OBSCommonUtils.pathToKey(owner, dst);

    if (srcKey.isEmpty()) {
      LOG.error("rename: src [{}] is root directory", src);
      throw new IOException(src + " is root directory");
    }

    // get the source file status; this raises a FNFE if there is no source
    // file.
    FileStatus srcStatus = owner.getFileStatus(src);

    FileStatus dstStatus;
    try {
      dstStatus = owner.getFileStatus(dst);
      // if there is no destination entry, an exception is raised.
      // hence this code sequence can assume that there is something
      // at the end of the path; the only detail being what it is and
      // whether or not it can be the destination of the rename.
      if (dstStatus.isDirectory()) {
        String newDstKey = OBSCommonUtils.maybeAddTrailingSlash(dstKey);
        String filename = srcKey.substring(
            OBSCommonUtils.pathToKey(owner, src.getParent()).length()
                + 1);

View on GitHub (pinned to 2add963021)

Solutions

  1. Reject or skip the operation when src.isRoot() (or when the key derived from it is empty)
  2. Fix the path computation that collapses to the bucket root
  3. Run jobs inside a dedicated prefix such as /user/ or /data/ instead of the bucket root

Example fix

// before
fs.rename(new Path("/"), new Path("/archive"));

// after
Path src = new Path("/data");
if (!src.isRoot()) {
  fs.rename(src, new Path("/archive/data"));
}
Defensive patterns

Strategy: validation

Validate before calling

if (src.isRoot()) {
  throw new IllegalArgumentException("Refusing to rename the bucket root: " + src);
}
// safer for arbitrary paths:
if (fs.getFileStatus(src).isDirectory() && src.isRoot()) {
  throw new IllegalArgumentException("Source is the bucket root");
}

Type guard

static boolean isBucketRoot(Path p) {
  return p.isRoot();
}

Try / catch

try {
  fs.rename(src, dst);
} catch (IOException e) {
  if (e.getMessage() != null && e.getMessage().endsWith("is root directory")) {
    // source resolved to the bucket root: fix the source path
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: FileSystem.rename(new Path("/"), dst) on an OBS object bucket; renaming obs://bucket/ directly; path arithmetic that strips the entire prefix; a loop on getParent() that terminates at root (Path.getParent() of the root returns the root itself) and then feeds it to rename.

Common situations: Compaction or migration jobs whose source directory is computed from configuration and defaults to the bucket root; cleanup utilities that walk upward to the top; staging-directory moves where the configured source is empty or '/'

Related errors


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