apache/hadoop · error · IOException
Cannot rename {absoluteSrc} under itself : {absoluteDst}
Error message
Cannot rename {absoluteSrc} under itself : {absoluteDst} What it means
rename() blocks moving a directory into its own subtree: after both paths are made absolute, isParentOf(absoluteSrc, absoluteDst) detects that dst lives under src and throws IOException("Cannot rename <src> under itself : <dst>"). Such a move is logically self-contradictory, and FTP rename could not express it anyway.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java:691
Path workDir = new Path(client.printWorkingDirectory());
Path absoluteSrc = makeAbsolute(workDir, src);
Path absoluteDst = makeAbsolute(workDir, dst);
if (!exists(client, absoluteSrc)) {
throw new FileNotFoundException("Source path " + src + " does not exist");
}
if (isDirectory(absoluteDst)) {
// destination is a directory: rename goes underneath it with the
// source name
absoluteDst = new Path(absoluteDst, absoluteSrc.getName());
}
if (exists(client, absoluteDst)) {
throw new FileAlreadyExistsException("Destination path " + dst
+ " already exists");
}
URI parentSrc = absoluteSrc.getParent().toUri();
URI parentDst = absoluteDst.getParent().toUri();
if (isParentOf(absoluteSrc, absoluteDst)) {
throw new IOException("Cannot rename " + absoluteSrc + " under itself"
+ " : "+ absoluteDst);
}
if (!parentSrc.toString().equals(parentDst.toString())) {
throw new IOException("Cannot rename source: " + absoluteSrc
+ " to " + absoluteDst
+ " -"+ E_SAME_DIRECTORY_ONLY);
}
String from = absoluteSrc.getName();
String to = absoluteDst.getName();
client.changeWorkingDirectory(parentSrc.getPath());
boolean renamed = client.rename(from, to);
return renamed;
}
@Override
public Path getWorkingDirectory() {
// Return home directory always since we do not maintain state.View on GitHub (pinned to 2add963021)
Solutions
- Pick a destination outside the source subtree, e.g. a sibling directory (rename "/data" to "/data-old")
- When nesting is required, copy-then-delete instead of rename: FileUtil.copy(fs, src, fs, dst, true, conf)
- Guard path construction: reject any dst whose qualified path starts with the qualified src path + "/"
Example fix
// before
fs.rename(new Path("/data"), new Path("/data/archive")); // IOException: under itself
// after
Path src = new Path("/data");
Path dst = new Path("/data-old"); // sibling, not a child of src
fs.rename(src, dst); Defensive patterns
Strategy: validation
Validate before calling
// reject destinations inside the source subtree before calling rename
String s = src.makeQualified(fs).toUri().getPath();
String d = dst.makeQualified(fs).toUri().getPath();
if (d.startsWith(s.endsWith("/") ? s : s + "/")) {
throw new IllegalArgumentException("dst is inside src: " + d);
}
fs.rename(src, dst); Try / catch
catch IOException from rename, check message for "under itself", and re-run with a destination outside the subtree or fall back to copy+delete.
Prevention
- Compose archive destinations as siblings, never children, of the source
- Unit-test path-building helpers with src == dst-parent cases
- For nesting moves, plan copy-then-delete from the start
When it happens
Trigger: rename("/data", "/data/archive/data") or any dst whose path has src as an ancestor; programmatic destination construction that nests the source inside itself (dst = src + "/old"); archive loops that build output paths under input paths.
Common situations: Archive/cleanup jobs deriving the destination from the source path (src + "/archive"); compaction flows moving a parent into a child; UI drag-and-drop letting users drop a folder into itself.
Related errors
- Rename to subdir is forbidden
- Source path {src} does not exist
- Destination path {dst} already exists
- Cannot rename source: {absoluteSrc} to {absoluteDst} -only s
- Source path and dest path refer the same file or directory
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/28b3141e9f799025.
Report an issue: GitHub.