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
- Reject or skip the operation when src.isRoot() (or when the key derived from it is empty)
- Fix the path computation that collapses to the bucket root
- 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
- Guard isRoot() before any rename or delete loop
- Treat an empty key derived from a path as invalid input
- Unit-test path arithmetic with the root path as a boundary case
- Run jobs inside dedicated prefixes, never against the bucket top level
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
- new destination is an existed directory
- new destination is an existed file
- destination is an existed file
- destination parent [{}] is not a directory
- destination has no parent
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/88963d1e41c5b0c3.
Report an issue: GitHub.