apache/hadoop · error · IOException
It is not allowed to rename a parent directory: %s to its su
Error message
It is not allowed to rename a parent directory: %s to its subdirectory: %s
What it means
rename walks dst's parent chain; if src itself appears among dst's ancestors (dst lies inside src, e.g. rename('/a','/a/b/c')) it throws IOException. Moving a directory into its own subtree would create a cycle, so CosN rejects it before any destination-existence checks run. The loop terminates with dstParentPath non-null exactly when src is an ancestor of dst.
Source
Thrown at hadoop-cloud-storage-project/hadoop-cos/src/main/java/org/apache/hadoop/fs/cosn/CosNFileSystem.java:639
+ "the same file or directory");
}
// It is not allowed to rename a parent directory to its subdirectory
Path dstParentPath;
for (dstParentPath = dst.getParent();
null != dstParentPath && !src.equals(dstParentPath);
dstParentPath = dstParentPath.getParent()) {
// Recursively find the common parent path of the source and
// destination paths.
LOG.debug("Recursively find the common parent directory of the source "
+ "and destination paths. The currently found parent path: {}",
dstParentPath);
}
if (null != dstParentPath) {
LOG.debug("It is not allowed to rename a parent directory:[{}] "
+ "to its subdirectory:[{}].", src, dst);
throw new IOException(String.format(
"It is not allowed to rename a parent directory: %s "
+ "to its subdirectory: %s", src, dst));
}
FileStatus dstFileStatus;
try {
dstFileStatus = this.getFileStatus(dst);
// The destination path exists and is a file,
// and the rename operation is not allowed.
if (dstFileStatus.isFile()) {
throw new FileAlreadyExistsException(String.format(
"File: %s already exists", dstFileStatus.getPath()));
} else {
// The destination path is an existing directory,
// and it is checked whether there is a file or directory
// with the same name as the source path under the destination path
dst = new Path(dst, src.getName());View on GitHub (pinned to 2add963021)
Solutions
- Choose a destination outside the source subtree (e.g. /archive/day instead of /data/day/archive when renaming /data/day).
- If nesting is genuinely required, copy with FileUtil.copy(fs, src, fs, dst, true, conf) and then delete the source.
- Validate before calling: walk dst's parents and fail fast if any equals src.
Example fix
// before
fs.rename(new Path('/data/day=22'), new Path('/data/day=22/archive')); // IOException
// after
fs.rename(new Path('/data/day=22'), new Path('/archive/day=22')); Defensive patterns
Strategy: validation
Validate before calling
for (Path anc = dst.getParent(); anc != null; anc = anc.getParent()) {
if (anc.equals(src)) {
throw new IllegalArgumentException('Destination lies inside source: ' + dst);
}
} Try / catch
try {
fs.rename(src, dst);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().contains('subdirectory')) {
// pick a destination outside the subtree, or copy+delete
FileUtil.copy(fs, src, fs, outsideDst, true, conf);
fs.delete(src, true);
} else { throw e; }
} Prevention
- Never build destinations by appending suffixes under the source path
- Archive into a sibling or external prefix, not into the source subtree
- Validate dst lineage against src before every directory rename
When it happens
Trigger: fs.rename(new Path('/a'), new Path('/a/b/c')); archive/rollup jobs moving a date directory into a subdirectory of itself; destination built by appending a suffix under the source path (e.g. /logs into /logs/archive).
Common situations: Archive scripts computing destination as source path + suffix; misordered arguments in a move utility; log rotation moving a directory into its own archive subfolder.
Related errors
- can not copy a directory to a subdirectory of self
- Source path and dest path refer the same file or directory
- File: %s already exists
- Cannot rename %s to %s, %s is a file
- {} already exists
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/7eeeb6ea490d0486.
Report an issue: GitHub.