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

  1. Delete the existing file first or pass overwrite=true when the target is a regular file
  2. Use a unique target name (part-<attemptId>) to avoid collisions on retries
  3. Check exists(f) && !isDirectory(f) before appending
  4. 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

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


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/728bcde9892e16f5. Report an issue: GitHub.