apache/hadoop · error · IOException

Cannot rename the root directory

Error message

Cannot rename the root directory %s to another name

What it means

checkAndGetSrcStatus() throws IOException when rename() is called with the root directory ('tos://bucket/') as source. The root is the bucket mount point and cannot be renamed or moved, so the request is rejected before any validation of the destination.

Solutions

  1. Do not rename the root; enumerate children and rename them individually
  2. Validate src before calling rename: reject src.isRoot() with a clear application-level error
  3. Restructure so the movable unit is a top-level prefix, not the bucket itself

Example fix

// before
fs.rename(new Path("/"), new Path("/backup")); // root as src -> IOException

// after: move top-level entries instead of the root
for (FileStatus st : fs.listStatus(new Path("/"))) {
  fs.rename(st.getPath(), new Path("/backup", st.getPath().getName()));
}
Defensive patterns

Strategy: validation

Validate before calling

Path q = src.makeQualified(fs.getUri(), fs.getWorkingDirectory());
if (q.isRoot() || q.toUri().getPath().equals("/")) {
  throw new IllegalArgumentException("refusing to rename the bucket root");
}

Prevention

When it happens

Trigger: fs.rename(new Path("/"), anyDest) or any path that resolves to the empty object key (the bucket root), e.g. rename('tos://bucket', 'tos://bucket/backup').

Common situations: Backup/archive scripts that try to move the whole bucket namespace; code that computes src from user input without validating it is not root; recursive 'move everything' utilities.

Related errors


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

Appendix: source

Thrown at hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/RawFileSystem.java:328

    // 4. Ensure the destination path doesn't exist.
    FileStatus finalDstStatus = destStatus;
    if (destStatus != null && destStatus.isDirectory()) {
      finalDstStatus = getFileStatusOrNull(finalDstPath);
    }
    if (finalDstStatus != null) {
      throw new FileAlreadyExistsException(
          String.format("Failed to rename since the dest path %s already exists.", finalDstPath));
    } else {
      return finalDstPath;
    }
  }

  private FileStatus checkAndGetSrcStatus(Path src) throws IOException {
    // throw FileNotFoundException if src not found.
    FileStatus srcStatus = innerFileStatus(src);

    if (src.isRoot()) {
      throw new IOException(String.format("Cannot rename the root directory %s to another name",
          src));
    }
    return srcStatus;
  }

  @Override
  public boolean delete(Path f, boolean recursive) throws IOException {
    LOG.debug("Delete path {} - recursive {}", f, recursive);
    try {
      FileStatus fileStatus = getFileStatus(f);
      Path path = fileStatus.getPath();

      if (path.isRoot()) {
        return deleteRoot(path, recursive);
      } else {
        if (fileStatus.isDirectory()) {
          fsOps.deleteDir(path, recursive);
        } else {

View on GitHub (pinned to 2add963021)