apache/iceberg · error · AlreadyExistsException

Location already exists: %s

Error message

Location already exists: %s

What it means

S3OutputFile.create() checks exists() first and throws AlreadyExistsException if an object is already present at the location. Iceberg's FileIO contract: create() fails if the file exists, while createOrOverwrite() silently replaces it.

Source

Thrown at aws/src/main/java/org/apache/iceberg/aws/s3/S3OutputFile.java:66

      S3AsyncClient asyncClient,
      S3URI uri,
      S3FileIOProperties s3FileIOProperties,
      MetricsContext metrics) {
    super(client, asyncClient, uri, s3FileIOProperties, metrics);
  }

  /**
   * Create an output stream for the specified location if the target object does not exist in S3 at
   * the time of invocation.
   *
   * @return output stream
   */
  @Override
  public PositionOutputStream create() {
    if (!exists()) {
      return createOrOverwrite();
    } else {
      throw new AlreadyExistsException("Location already exists: %s", uri());
    }
  }

  @Override
  public PositionOutputStream createOrOverwrite() {
    try {
      return new S3OutputStream(client(), uri(), s3FileIOProperties(), metrics());
    } catch (IOException e) {
      throw new UncheckedIOException("Failed to create output stream for location: " + uri(), e);
    }
  }

  @Override
  public InputFile toInputFile() {
    return new S3InputFile(client(), asyncClient(), uri(), null, s3FileIOProperties(), metrics());
  }

  @Override

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Use createOrOverwrite() if replacing the existing object is acceptable.
  2. Choose a unique output path (UUID/timestamp suffix) before calling create().
  3. Delete the existing object first if it is a stale artifact.
  4. Add concurrency control (e.g. task attempt paths) so parallel writers do not collide.

Example fix

// before
OutputFile out = io.newOutputFile("s3://bucket/data/file.parquet");
PositionOutputStream s = out.create(); // AlreadyExistsException
// after
OutputFile out = io.newOutputFile("s3://bucket/data/file-" + UUID.randomUUID() + ".parquet");
PositionOutputStream s = out.createOrOverwrite();
Defensive patterns

Strategy: try-catch

Validate before calling

// Java
OutputFile out = io.newOutputFile(path);
if (out.exists()) {
  path = path + "-" + UUID.randomUUID();
  out = io.newOutputFile(path);
}

Try / catch

// Java
try {
  os = outFile.create();
} catch (AlreadyExistsException e) {
  os = outFile.createOrOverwrite(); // or regenerate a unique path
}

Prevention

When it happens

Trigger: Calling S3OutputFile.create() when an object already exists at the S3 URI; also produced when create() internally calls exists() and S3 reports the key present (e.g. a leftover object from a failed previous write).

Common situations: Writing a data/manifest file to a path reused after a failed job; two concurrent writers choosing the same path; accidentally passing a directory-like or existing key to create().

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/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/6306fc937766d91e. Report an issue: GitHub.