apache/hadoop · error · IOException
Cannot rename source: {absoluteSrc} to {absoluteDst} -only s
Error message
Cannot rename source: {absoluteSrc} to {absoluteDst} -only same directory renames are supported What it means
FTP's RNFR/RNTO can only rename an entry within its parent directory. FTPFileSystem enforces this: if the parent directories of the absolute source and destination differ (compared as parent URIs), it throws IOException("Cannot rename source ... - only same directory renames are supported") without contacting the server.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java:696
}
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.
return getHomeDirectory();
}
@Override
public Path getHomeDirectory() {View on GitHub (pinned to 2add963021)
Solutions
- Implement move as copy + delete: FileUtil.copy(fs, src, fs, dst, true, conf)
- If you only mean to rename, keep both paths inside the same parent directory
- Normalize both parents (makeQualified + getParent().toUri()) before assuming they are equal or different
- Stage data on HDFS/local when frequent moves are needed; treat FTP purely as a transfer source/sink
Example fix
// before
fs.rename(new Path("/incoming/f.dat"), new Path("/archive/f.dat")); // same-dir only -> IOException
// after
boolean moved = FileUtil.copy(fs, src, fs, dst, /*deleteSource*/ true, conf);
if (!moved) {
throw new IOException("copy-move failed: " + src + " -> " + dst);
} Defensive patterns
Strategy: validation
Validate before calling
// only same-parent renames are supported on ftp://
if (!src.getParent().equals(dst.getParent())) {
boolean moved = FileUtil.copy(fs, src, fs, dst, /*deleteSource*/ true, conf);
if (!moved) { throw new IOException("copy-move failed: " + src); }
} else {
fs.rename(src, dst);
} Try / catch
catch IOException containing "only same directory renames are supported" and fall back to FileUtil.copy with deleteSource=true.
Prevention
- Treat ftp:// rename as rename-in-place only; use copy+delete for moves
- Normalize both parents before comparing (encoding, trailing slashes)
- Stage files on HDFS/local when the workflow needs frequent moves
When it happens
Trigger: rename("/dir1/file", "/dir2/file") or any dst whose parent differs from src's parent, including "move into another directory" intentions; also URI normalization differences (trailing slash, encoding) making equal parents compare unequal as strings.
Common situations: Porting code from LocalFileSystem/HDFS where cross-directory rename works; ingest flows trying to "move" files between FTP directories over an ftp:// URL; path strings assembled with inconsistent encoding or slashes so the parent string comparison fails even in the same directory.
Related errors
- Source path {src} does not exist
- Destination path {dst} already exists
- Cannot rename {absoluteSrc} under itself : {absoluteDst}
- Seek not supported
- Mark not supported
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/84f580fa75809498.
Report an issue: GitHub.