apache/hadoop · error · IOException
Failed to rename since it is prohibited to rename dest path
Error message
Failed to rename since it is prohibited to rename dest path %s under src path %s
What it means
Thrown by the rename-destination validation in RawFileSystem when the final destination path is inside the source subtree (RawFSUtils.inSubtree(src, finalDstPath) is true). Renaming a directory into its own descendant would create a cycle, so the operation is rejected before any storage call.
Source
Thrown at hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/RawFileSystem.java:306
return true;
}
private Path checkAndGetDstPath(Path src, Path dest) throws IOException {
FileStatus destStatus = getFileStatusOrNull(dest);
// 1. Rebuilding the destination path
Path finalDstPath = dest;
if (destStatus != null && destStatus.isDirectory()) {
finalDstPath = new Path(dest, src.getName());
}
// 2. No need to check the dest path because renaming itself is allowed.
if (src.equals(finalDstPath)) {
return finalDstPath;
}
// 3. Ensure the source path cannot be the ancestor of destination path.
if (RawFSUtils.inSubtree(src, finalDstPath)) {
throw new IOException(String.format("Failed to rename since it is prohibited to " +
"rename dest path %s under src path %s", finalDstPath, src));
}
// 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.View on GitHub (pinned to 2add963021)
Solutions
- Choose a destination outside the source subtree, e.g. rename('/a/b', '/a/c') instead of rename('/a/b', '/a/b/c')
- If the intent is to move under a sibling directory, target the sibling: rename('/a/b', '/a-dst/b')
- Validate before calling: reject when dest.isDescendant(src) (or use RawFSUtils.inSubtree semantics) with your own error message
Example fix
// before
fs.rename(new Path("/a/b"), new Path("/a/b/c")); // dest under src -> IOException
// after
fs.rename(new Path("/a/b"), new Path("/a/c")); // dest outside src subtree Defensive patterns
Strategy: validation
Validate before calling
static boolean isUnder(Path src, Path dst) {
// true when dst is a descendant of src
for (Path p = dst.getParent(); p != null; p = p.getParent()) {
if (p.equals(src)) return true;
}
return false;
}
if (isUnder(makeQualified(src), makeQualified(dst))) throw new IllegalArgumentException("dest under src"); Try / catch
try { fs.rename(src, dst); }
catch (IOException e) {
if (e.getMessage() != null && e.getMessage().contains("prohibited to rename")) { /* fix paths */ }
else throw e;
} Prevention
- Compute destination paths from a different root than the source
- Unit-test rename helpers with the 'into own subtree' case
- Remember dest-dir adjustment: dest may become dest/srcName before validation
When it happens
Trigger: rename('/a/b', '/a/b/c') or any rename where dest (after the 'dest is an existing dir' adjustment of appending src.getName()) is a strict descendant of src, e.g. renaming a directory into a subdirectory of itself.
Common situations: Shell-script style 'move into self' mistakes ported to the object store; job code computing destination paths from source paths and accidentally nesting them; archive routines that build dest as src + '/archive'.
Related errors
- Cannot rename the root directory %s to another name
- It is not allowed to rename a parent directory: %s to its su
- A file cannot be created in root.
- Rename to subdir is forbidden
- Failed to rename since the dest path %s already exists.
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/6f3674a787f6cef7.
Report an issue: GitHub.