juicedata/juicefs · error · FileAlreadyExistsException
Path already exists: " + f
Error message
Path already exists: " + f
What it means
Thrown by append() when the native jfs_open (append mode) returns EEXIST, i.e. the target path already exists, and the caller did not request overwrite (or the path is a directory). This mirrors Hadoop's FileAlreadyExistsException contract for append/create conflicts.
Source
Thrown at sdk/java/src/main/java/io/juicefs/JuiceFileSystemImpl.java:1472
return superGroupFileSystem.create(f, permission, overwrite, bufferSize, replication, blockSize, progress);
} else if (!checkPathAccess(f, FsAction.WRITE, "create")) {
return superGroupFileSystem.create(f, permission, overwrite, bufferSize, replication, blockSize, progress);
}
}
statistics.incrementWriteOps(1);
while (true) {
int fd = lib.jfs_create(Thread.currentThread().getId(), handle, normalizePath(f), permission.toShort(), uMask.toShort());
if (fd == ENOENT) {
Path parent = makeQualified(f).getParent();
try {
mkdirs(parent, FsPermission.getDirDefault());
} catch (FileAlreadyExistsException e) {
}
continue;
}
if (fd == EEXIST) {
if (!overwrite || isDirectory(f)) {
throw new FileAlreadyExistsException("Path already exists: " + f);
}
delete(f, false);
continue;
}
if (fd < 0) {
throw error(fd, makeQualified(f).getParent());
}
return createFsDataOutputStream(f, bufferSize, fd, 0L);
}
}
private int checkBufferSize(int size) {
if (size < minBufferSize) {
size = minBufferSize;
}
return size;
}
View on GitHub (pinned to c9a67b23e8)
Solutions
- Delete the existing file first or pass overwrite=true when the target is a regular file
- Use a unique target name (part-<attemptId>) to avoid collisions on retries
- Check exists(f) && !isDirectory(f) before appending
- Catch FileAlreadyExistsException and branch to a new path or resume logic
Example fix
// before
FSDataOutputStream out = fs.append(path); // throws if exists
// after
if (fs.exists(path)) { fs.delete(path, false); }
FSDataOutputStream out = fs.append(path); Defensive patterns
Strategy: try-catch
Validate before calling
if (fs.exists(path) && fs.isDirectory(path)) throw new IllegalArgumentException("target is a directory: " + path); Try / catch
try { return fs.append(path); } catch (FileAlreadyExistsException e) { fs.delete(path, false); return fs.append(path); } Prevention
- Check existence before append
- Use unique per-attempt file names
- Ensure overwrite flag matches intent
- Never append to directory paths
When it happens
Trigger: append(f) called on a path that exists while overwrite is false; append with overwrite=true but the target is an existing directory; two writers racing to append/create the same path.
Common situations: Job retries re-attempting an append to a file from a previous failed attempt; treating an existing directory path as a file target; concurrent tasks writing to the same output path without unique names.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- File already exists: " + f
- Invalid start or len parameter
- stream was closed
- arguments: " + off + " " + len
- position is negative
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/728bcde9892e16f5.
Report an issue: GitHub.