apache/hadoop · error · IllegalArgumentException
Move destination must be different from source for %s.
Error message
Move destination must be different from source for %s.
What it means
During move validation, after the cross-bucket check, the code rejects pairs where source and destination are the same bucket AND the same object name, throwing IllegalArgumentException("Move destination must be different from source for %s."). A self-move is a no-op at best and a livelock at worst, so the API demands callers filter it themselves.
Source
Thrown at hadoop-cloud-storage-project/hadoop-gcp/src/main/java/org/apache/hadoop/fs/gs/GoogleCloudStorage.java:730
for (Map.Entry<StorageResourceId, StorageResourceId> entry :
sourceToDestinationObjectsMap.entrySet()) {
StorageResourceId source = entry.getKey();
StorageResourceId destination = entry.getValue();
String srcBucketName = source.getBucketName();
String dstBucketName = destination.getBucketName();
// Avoid move across buckets.
if (!srcBucketName.equals(dstBucketName)) {
throw new UnsupportedOperationException(
"This operation is not supported across two different buckets.");
}
checkArgument(
!isNullOrEmpty(source.getObjectName()), "srcObjectName must not be null or empty");
checkArgument(
!isNullOrEmpty(destination.getObjectName()), "dstObjectName must not be null or empty");
if (srcBucketName.equals(dstBucketName)
&& source.getObjectName().equals(destination.getObjectName())) {
throw new IllegalArgumentException(
String.format(
"Move destination must be different from source for %s.",
StringPaths.fromComponents(srcBucketName, source.getObjectName())));
}
}
}
void copy(Map<StorageResourceId, StorageResourceId> sourceToDestinationObjectsMap)
throws IOException {
validateCopyArguments(sourceToDestinationObjectsMap, this);
if (sourceToDestinationObjectsMap.isEmpty()) {
return;
}
for (Map.Entry<StorageResourceId, StorageResourceId> entry :
sourceToDestinationObjectsMap.entrySet()) {
StorageResourceId srcObject = entry.getKey();View on GitHub (pinned to 2add963021)
Solutions
- Filter identity mappings before calling move: skip when src.equals(dst)
- Fix the destination-path computation so renames actually change the object name
- For fs.rename(path, path), short-circuit to success in calling code — it is a no-op
Example fix
// before
for (Map.Entry<StorageResourceId, StorageResourceId> e : moves.entrySet()) {
gcs.moveObjects(...); // may contain src==dst -> IllegalArgumentException
}
// after
for (Map.Entry<StorageResourceId, StorageResourceId> e : moves.entrySet()) {
if (!e.getKey().equals(e.getValue())) {
gcs.moveObjects(...);
}
} Defensive patterns
Strategy: validation
Validate before calling
// Drop identity mappings before moving Map<StorageResourceId, StorageResourceId> moves = ...; moves.entrySet().removeIf(e -> e.getKey().equals(e.getValue())); gcs.moveObjects(moves);
Prevention
- Skip src==dst pairs early — they are no-ops
- Unit-test destination-path computation for rename helpers
- Treat fs.rename(p, p) as success in wrappers
When it happens
Trigger: Calling move/rename with src == dst (identical bucket and object name), e.g. fs.rename(path, path), or a bulk move map that includes identity entries — often produced by directory-rename code that maps a parent onto itself for root entries.
Common situations: Rename loops that compute destination by string replacement and produce the same path; task commit moving files into a directory they are already in; recursive directory moves that include the directory itself in the file list.
Related errors
- This operation is not supported across two different buckets
- Object %s already exists.
- Error accessing Bucket %s
- Error accessing %s
- Bucket doesn't match for source '%s' and destination '%s'!
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/5f8efae25ae18c52.
Report an issue: GitHub.