apache/iceberg · error · AlreadyExistsException

Table already exists at location

Error message

Table already exists at location: %s

What it means

HadoopTables.build(...).create() throws AlreadyExistsException if newTableOps(location).current() is non-null, i.e., metadata already exists at the target location. Creation is not idempotent — it refuses to overwrite an existing table to prevent data loss.

Solutions

  1. Use createOrReplace() instead of create() when overwriting is intended
  2. Drop the existing table first (tables.dropTable(location))
  3. Pick a unique new location/table name
  4. Handle AlreadyExistsException and branch on desired semantics

Example fix

// before
builder.create(); // throws if exists
// after
try {
  builder.create();
} catch (AlreadyExistsException e) {
  tables.buildTable(location, schema).createOrReplace();
}
Defensive patterns

Strategy: validation

Validate before calling

HadoopTables tables = new HadoopTables(conf);
if (tables.exists(location)) { /* use createOrReplace or skip */ }

Try / catch

try { builder.create(); } catch (AlreadyExistsException e) { /* skip, replace, or fail deliberately */ }

Prevention

When it happens

Trigger: create() on a path where a table already exists; rerunning an idempotency-intended job without create-or-replace; createOrReplace vs create confusion; stale path left by a partially dropped table.

Common situations: Re-running a setup/seed job twice; table created concurrently by another job between the existence check and create; pointing a new table at an old location.

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/037ee0fa99b1e3e2. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/hadoop/HadoopTables.java:334

    @Override
    public Catalog.TableBuilder withProperties(Map<String, String> properties) {
      if (properties != null) {
        propertiesBuilder.putAll(properties);
      }
      return this;
    }

    @Override
    public Catalog.TableBuilder withProperty(String key, String value) {
      propertiesBuilder.put(key, value);
      return this;
    }

    @Override
    public Table create() {
      TableOperations ops = newTableOps(location);
      if (ops.current() != null) {
        throw new AlreadyExistsException("Table already exists at location: %s", location);
      }

      Map<String, String> properties = propertiesBuilder.build();
      TableMetadata metadata = tableMetadata(schema, spec, sortOrder, properties, location);
      ops.commit(null, metadata);
      return new BaseTable(ops, location);
    }

    @Override
    public Transaction createTransaction() {
      TableOperations ops = newTableOps(location);
      if (ops.current() != null) {
        throw new AlreadyExistsException("Table already exists: %s", location);
      }

      Map<String, String> properties = propertiesBuilder.build();
      TableMetadata metadata = tableMetadata(schema, spec, null, properties, location);
      return Transactions.createTableTransaction(location, ops, metadata);

View on GitHub (pinned to 86d9c8fc54)