apache/hadoop · error · FileAlreadyExistsException
The source {src} and destination {dst} are the same
Error message
The source {src} and destination {dst} are the same What it means
The default (non-atomic) rename-with-overwrite in AbstractFileSystem first stats both ends; when the destination exists and dst.equals(src) (Path equality is URI equality), it throws FileAlreadyExistsException — renaming an entry onto itself is refused as a no-op. A sibling branch also rejects renaming a symlink onto its own target.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/AbstractFileSystem.java:863
* @throws UnresolvedLinkException unresolved link exception.
* @throws IOException raised on errors performing I/O.
*/
public void renameInternal(final Path src, final Path dst,
boolean overwrite) throws AccessControlException,
FileAlreadyExistsException, FileNotFoundException,
ParentNotDirectoryException, UnresolvedLinkException, IOException {
// Default implementation deals with overwrite in a non-atomic way
final FileStatus srcStatus = getFileLinkStatus(src);
FileStatus dstStatus;
try {
dstStatus = getFileLinkStatus(dst);
} catch (IOException e) {
dstStatus = null;
}
if (dstStatus != null) {
if (dst.equals(src)) {
throw new FileAlreadyExistsException(
"The source "+src+" and destination "+dst+" are the same");
}
if (srcStatus.isSymlink() && dst.equals(srcStatus.getSymlink())) {
throw new FileAlreadyExistsException(
"Cannot rename symlink "+src+" to its target "+dst);
}
// It's OK to rename a file to a symlink and vice versa
if (srcStatus.isDirectory() != dstStatus.isDirectory()) {
throw new IOException("Source " + src + " and destination " + dst
+ " must both be directories");
}
if (!overwrite) {
throw new FileAlreadyExistsException("Rename destination " + dst
+ " already exists.");
}
// Delete the destination that is a file or an empty directory
if (dstStatus.isDirectory()) {
RemoteIterator<FileStatus> list = listStatusIterator(dst);View on GitHub (pinned to 2add963021)
Solutions
- Skip the operation when the fully-qualified paths are equal: if (fc.makeQualified(src).equals(fc.makeQualified(dst))) return;
- Fix the destination computation so it genuinely differs (distinct name, subdirectory, or timestamp suffix)
- Validate src != dst at the API boundary of your move/rename helpers and report it as a no-op, not an error
Example fix
// before
fc.rename(src, dst, Rename.OVERWRITE); // src and dst resolve to the same path
// after
if (!fc.makeQualified(src).equals(fc.makeQualified(dst))) {
fc.rename(src, dst, Rename.OVERWRITE);
} Defensive patterns
Strategy: validation
Validate before calling
Path qs = fc.makeQualified(src), qd = fc.makeQualified(dst);
if (qs.equals(qd)) {
return; // moving onto itself: treat as no-op
}
fc.rename(src, dst, Rename.OVERWRITE); Try / catch
catch (FileAlreadyExistsException e) { if (srcQualified.equals(dstQualified)) { /* no-op move: skip */ } else throw e; } Prevention
- Compare fully-qualified src and dst before every rename/move
- Ensure destination computation always produces a different path (suffix, subdirectory)
- Guard archive/compaction loops where filters can select nothing and degenerate dst to src
When it happens
Trigger: rename(a, a) with a existing; loops that compute a destination which degenerates to the source path ("move to same location"); dst produced by makeQualified/makeQualified-equivalent that ends up with the identical URI as src.
Common situations: Archive/compaction jobs whose filter selects nothing so the computed destination equals the input; output directory configured equal to input directory; distcp-style tooling where src and dst resolve to the same qualified path; renames inside loops with per-row destinations.
Related errors
- {} already exists
- File: %s already exists
- Cannot overwrite an existing file: %s
- Cannot rename because path does not exist: %s
- Rename dir to self is forbidden
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/cfc5fcd65ff30ded.
Report an issue: GitHub.