{"record":{"id":"9ce468b09730cee1","repo":"apache/hadoop","slug":"cannot-rename-the-root-directory-s-to-another-nam","errorCode":null,"errorMessage":"Cannot rename the root directory %s to another name","messagePattern":"Cannot rename the root directory (.+?) to another name","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/RawFileSystem.java","lineNumber":328,"sourceCode":"    // 4. Ensure the destination path doesn't exist.\n    FileStatus finalDstStatus = destStatus;\n    if (destStatus != null && destStatus.isDirectory()) {\n      finalDstStatus = getFileStatusOrNull(finalDstPath);\n    }\n    if (finalDstStatus != null) {\n      throw new FileAlreadyExistsException(\n          String.format(\"Failed to rename since the dest path %s already exists.\", finalDstPath));\n    } else {\n      return finalDstPath;\n    }\n  }\n\n  private FileStatus checkAndGetSrcStatus(Path src) throws IOException {\n    // throw FileNotFoundException if src not found.\n    FileStatus srcStatus = innerFileStatus(src);\n\n    if (src.isRoot()) {\n      throw new IOException(String.format(\"Cannot rename the root directory %s to another name\",\n          src));\n    }\n    return srcStatus;\n  }\n\n  @Override\n  public boolean delete(Path f, boolean recursive) throws IOException {\n    LOG.debug(\"Delete path {} - recursive {}\", f, recursive);\n    try {\n      FileStatus fileStatus = getFileStatus(f);\n      Path path = fileStatus.getPath();\n\n      if (path.isRoot()) {\n        return deleteRoot(path, recursive);\n      } else {\n        if (fileStatus.isDirectory()) {\n          fsOps.deleteDir(path, recursive);\n        } else {","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/RawFileSystem.java#L310-L346","documentation":"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.","triggerScenarios":"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').","commonSituations":"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.","solutions":["Do not rename the root; enumerate children and rename them individually","Validate src before calling rename: reject src.isRoot() with a clear application-level error","Restructure so the movable unit is a top-level prefix, not the bucket itself"],"exampleFix":"// before\nfs.rename(new Path(\"/\"), new Path(\"/backup\")); // root as src -> IOException\n\n// after: move top-level entries instead of the root\nfor (FileStatus st : fs.listStatus(new Path(\"/\"))) {\n  fs.rename(st.getPath(), new Path(\"/backup\", st.getPath().getName()));\n}","handlingStrategy":"validation","validationCode":"Path q = src.makeQualified(fs.getUri(), fs.getWorkingDirectory());\nif (q.isRoot() || q.toUri().getPath().equals(\"/\")) {\n  throw new IllegalArgumentException(\"refusing to rename the bucket root\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reject root in shared rename helpers before touching the FS","Enumerate-and-move children for whole-tree backups","Validate user-supplied paths resolve to non-root keys"],"tags":["rename","root-directory","path-validation","tos"],"backgroundTag":"root-directory-protected","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}