apache/seatunnel · error · IOException

File already exists: %s

Error message

File already exists: %s

What it means

create() checks exists(client, f) and, when overwrite=false, throws IOException(E_FILE_EXIST) instead of replacing the file. Hadoop-compatible create semantics: an existing file is only deleted when overwrite is true; otherwise creation is refused.

Source

Thrown at seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/system/SFTPFileSystem.java:528

    @Override
    public FSDataOutputStream create(
            Path f,
            FsPermission permission,
            boolean overwrite,
            int bufferSize,
            short replication,
            long blockSize,
            Progressable progress)
            throws IOException {
        final ChannelSftp client = connect();
        try {
            Path workDir = new Path(client.pwd());
            Path absolute = makeAbsolute(workDir, f);
            if (exists(client, f)) {
                if (overwrite) {
                    delete(client, f, false);
                } else {
                    throw new IOException(String.format(E_FILE_EXIST, f));
                }
            }
            Path parent = absolute.getParent();
            if (parent == null || !mkdirs(client, parent, FsPermission.getDefault())) {
                parent = (parent == null) ? new Path("/") : parent;
                throw new IOException(String.format(E_CREATE_DIR, parent));
            }
            final String previousCwd = client.pwd();
            client.cd(parent.toUri().getPath());
            OutputStream os = client.put(f.getName());
            client.cd(previousCwd);
            return new FSDataOutputStream(os, statistics) {
                @Override
                public void close() throws IOException {
                    try {
                        super.close();
                    } finally {
                        disconnect(client);

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Enable overwrite: fs.create(path, true) or set the connector's overwrite/replace option
  2. Delete the existing file before creating: fs.delete(path, false)
  3. Write to a unique output path per run (timestamped / attempt-scoped)
  4. Check fs.exists(path) beforehand and fail fast with a clear message

Example fix

// before
FSDataOutputStream out = fs.create(path, false);
// after
FSDataOutputStream out = fs.create(path, true);
Defensive patterns

Strategy: validation

Validate before calling

Path out = new Path("/data/out/result");
if (fs.exists(out) && !overwriteAllowed) {
    throw new IOException("Output exists, overwrite disabled: " + out);
}

Try / catch

try {
    FSDataOutputStream out = fs.create(path, false);
} catch (IOException e) {
    if (String.valueOf(e.getMessage()).contains("already exists")) {
        FSDataOutputStream out = fs.create(path, true); // if overwrite is acceptable
    } else { throw e; }
}

Prevention

When it happens

Trigger: fs.create(path) (or connector sink setup creating the output file) where the target file already exists and the overwrite flag is false.

Common situations: Re-running a batch job against the same output path without cleanup; sink configured without overwrite enabled; leftover partial output from a failed run; two jobs writing the same target concurrently.

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 apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/06d1cb77e653d60c. Report an issue: GitHub.