apache/iceberg · error · org.apache.spark.sql.catalyst.analysis.TableAlreadyExistsException

TableAlreadyExistsException

Error message

TableAlreadyExistsException: <ident>

What it means

When SparkCatalog.createTable calls the underlying Iceberg catalog's create(), the catalog may reject the creation because a table (or its metadata file) already exists at that identifier, surfacing AlreadyExistsException. Spark translates this into Spark's TableAlreadyExistsException carrying the identifier.

Solutions

  1. Use CREATE TABLE IF NOT EXISTS if the table existing is acceptable.
  2. Drop the existing table first (DROP TABLE) if it should be recreated.
  3. Use CREATE OR REPLACE TABLE when intentional replacement is desired.
  4. If caused by orphan metadata files, clean the stale metadata at the table location before retrying.

Example fix

-- before
CREATE TABLE catalog.db.t (id bigint) USING iceberg; -- throws if t exists
-- after
CREATE TABLE IF NOT EXISTS catalog.db.t (id bigint) USING iceberg;
Defensive patterns

Strategy: try-catch

Validate before calling

-- Spark SQL precheck
SHOW TABLES IN catalog.db LIKE 't';

Try / catch

try {
  spark.sql("CREATE TABLE catalog.db.t ... ");
} catch (TableAlreadyExistsException e) {
  // idempotent path: skip or replace
  spark.sql("CREATE TABLE IF NOT EXISTS catalog.db.t ...");
}

Prevention

When it happens

Trigger: Executing CREATE TABLE (without IF NOT EXISTS / OR REPLACE) on an identifier that already exists in the Iceberg catalog, or a stale metadata file at the target location causing an AlreadyExistsException during commit.

Common situations: Rerunning idempotent-looking DDL scripts without IF NOT EXISTS; concurrent jobs creating the same table; leftover metadata files from a failed/aborted create at the same 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/717029be997bcd23. Report an issue: GitHub.

Appendix: source

Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java:219

    }
  }

  @Override
  public Table createTable(
      Identifier ident, StructType schema, Transform[] transforms, Map<String, String> properties)
      throws TableAlreadyExistsException {
    Schema icebergSchema = SparkSchemaUtil.convert(schema);
    try {
      Catalog.TableBuilder builder = newBuilder(ident, icebergSchema);
      org.apache.iceberg.Table icebergTable =
          builder
              .withPartitionSpec(Spark3Util.toPartitionSpec(icebergSchema, transforms))
              .withLocation(properties.get("location"))
              .withProperties(Spark3Util.rebuildCreateProperties(properties))
              .create();
      return new SparkTable(icebergTable);
    } catch (AlreadyExistsException e) {
      throw new TableAlreadyExistsException(ident);
    }
  }

  @Override
  public StagedTable stageCreate(
      Identifier ident, StructType schema, Transform[] transforms, Map<String, String> properties)
      throws TableAlreadyExistsException {
    Schema icebergSchema = SparkSchemaUtil.convert(schema);
    try {
      Catalog.TableBuilder builder = newBuilder(ident, icebergSchema);
      Transaction transaction =
          builder
              .withPartitionSpec(Spark3Util.toPartitionSpec(icebergSchema, transforms))
              .withLocation(properties.get("location"))
              .withProperties(Spark3Util.rebuildCreateProperties(properties))
              .createTransaction();
      return new StagedSparkTable(transaction);
    } catch (AlreadyExistsException e) {

View on GitHub (pinned to 86d9c8fc54)