apache/hadoop · error · IOException
Cannot overwrite an existing file
Error message
Cannot overwrite an existing file: %s
What it means
Thrown by GoogleCloudStorageFileSystem.getDstUri (hadoop-gcp) while computing the effective destination of a rename: the destination exists as a file AND either the source is a directory or the destination differs from the source. The GCS connector implements Hadoop rename semantics, which never overwrite an existing destination file, so it refuses the operation up front.
Solutions
- Delete or move the existing destination file first (fs.delete(dst, false) after fs.exists(dst) && !fs.getFileStatus(dst).isDirectory()).
- Rename to a fresh, non-existent destination (append a unique suffix/UUID if the name matters).
- If re-running a failed pipeline, clean up partial outputs before the rename stage.
- Treat this IOException as a 'destination exists' signal in caller logic instead of retrying the identical rename.
Example fix
// before
Path src = new Path("gs://bucket/a.txt");
Path dst = new Path("gs://bucket/b.txt"); // b.txt already exists -> IOException
fs.rename(src, dst);
// after
if (fs.exists(dst) && !fs.getFileStatus(dst).isDirectory()) {
fs.delete(dst, false);
}
fs.rename(src, dst); Defensive patterns
Strategy: validation
Validate before calling
Path src = new Path("gs://bucket/a.txt");
Path dst = new Path("gs://bucket/b.txt");
FileSystem fs = src.getFileSystem(conf);
if (fs.exists(dst) && !fs.getFileStatus(dst).isDirectory()) {
fs.delete(dst, false); // or pick a unique destination name instead
}
boolean renamed = fs.rename(src, dst); Try / catch
catch IOException around rename; check message startsWith("Cannot overwrite an existing file") to distinguish a destination conflict from transient GCS errors - retrying the same rename will not help, so delete or rename aside the destination instead. Prevention
- Never assume POSIX mv overwrite semantics - Hadoop rename never overwrites an existing file on GCS.
- Generate destination names deterministically-unique (or check exists) in retryable pipelines.
- Clean up outputs of failed runs before re-running rename stages.
When it happens
Trigger: Calling gcsFs.rename(srcUri, dstUri) or GoogleHadoopFileSystem.rename(Path, Path) where getFileInfo(dst) reports an existing file and (srcInfo.isDirectory() || !dst.equals(src)). Examples: renaming gs://b/a.txt onto existing file gs://b/b.txt; renaming a directory onto an existing file path; 'mv foo bar' style calls where bar is already a file.
Common situations: Pipelines that write to temp names then rename onto final names that already exist from a previous failed run; idempotent job retries that repeat a rename step; developers assuming POSIX 'mv' overwrite behavior; Hive/Spark commit phases moving staging files onto existing output paths.
Related errors
- Cannot rename because path does not exist
- Destination path already exist, cannot rename!
- doesn't support renameSnapshot
- GoogleHadoopFileSystem has been closed or not initialized.
- rename cannot overwrite non empty destination directory
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/a0445c05c8182ec9.
Report an issue: GitHub.
Appendix: source
Thrown at hadoop-cloud-storage-project/hadoop-gcp/src/main/java/org/apache/hadoop/fs/gs/GoogleCloudStorageFileSystem.java:560
result.add(getFileInfo(path));
}
return result;
}
private URI getDstUri(FileInfo srcInfo, FileInfo dstInfo, @Nullable FileInfo dstParentInfo)
throws IOException {
URI src = srcInfo.getPath();
URI dst = dstInfo.getPath();
// Throw if src is a file and dst == GCS_ROOT
if (!srcInfo.isDirectory() && dst.equals(GCSROOT)) {
throw new IOException("A file cannot be created in root.");
}
// Throw if the destination is a file that already exists, and it's not a source file.
if (dstInfo.exists() && !dstInfo.isDirectory() && (srcInfo.isDirectory() || !dst.equals(src))) {
throw new IOException("Cannot overwrite an existing file: " + dst);
}
// Rename operation cannot be completed if parent of destination does not exist.
if (dstParentInfo != null && !dstParentInfo.exists()) {
throw new IOException(
"Cannot rename because path does not exist: " + dstParentInfo.getPath());
}
// Leaf item of the source path.
String srcItemName = getItemName(src);
// Having taken care of the initial checks, apply the regular rules.
// After applying the rules, we will be left with 2 paths such that:
// -- either both are files or both are directories
// -- src exists and dst leaf does not exist
if (srcInfo.isDirectory()) {
// -- if src is a directory
// -- dst is an existing file => disallowedView on GitHub (pinned to 2add963021)