apache/iceberg · error · org.apache.spark.sql.catalyst.analysis.TableAlreadyExistsException
Table already exists
Error message
Table already exists: %s
What it means
Spark's catalog API signals that a CREATE TABLE was issued for an identifier that already exists in the Iceberg catalog. SparkCatalog.createTable catches Iceberg's AlreadyExistsException from the underlying catalog's create() call and rethrows Spark's own org.apache.spark.sql.catalyst.analysis.TableAlreadyExistsException so Spark session/analysis layers handle it consistently.
Solutions
- Use CREATE TABLE IF NOT EXISTS, or check catalog.tableExists(ident) before creating.
- Wrap creation in try-catch on TableAlreadyExistsException and reuse the existing table.
- Drop the stale table first (DROP TABLE) if it is safe to recreate.
- Verify you are writing to the intended catalog/namespace (spark.sql.catalog.* configuration).
Example fix
// before
spark.sql("CREATE TABLE db.events (id BIGINT) USING iceberg")
// after
spark.sql("CREATE TABLE IF NOT EXISTS db.events (id BIGINT) USING iceberg") Defensive patterns
Strategy: try-catch
Validate before calling
if (spark.catalog().tableExists("db", "events")) { /* reuse or skip */ } Type guard
boolean isFresh = spark instanceof SparkSession s && !s.catalog().tableExists(ident.namespace(), ident.name());
Try / catch
try { catalog.createTable(ident, schema, transforms, props); } catch (TableAlreadyExistsException e) { table = catalog.loadTable(ident); } Prevention
- Prefer IF NOT EXISTS in DDL scripts.
- Make migration scripts idempotent.
- Qualify identifiers with the intended catalog name.
- Check tableExists before programmatic creation.
When it happens
Trigger: Calling CREATE TABLE (or DataFrameWriter.saveAsTable with mode ErrorIfExists/default) for an identifier that already exists; also CREATE TABLE without IF NOT EXISTS; the underlying icebergCatalog.create() throws AlreadyExistsException which is converted at line 267.
Common situations: Re-running a notebook or migration script that creates tables idempotently without IF NOT EXISTS; two jobs racing to create the same table; Spark session pointing at a catalog/namespace different from the one the developer assumed (table exists there); Hive vs Hadoop catalog confusion in multi-catalog setups.
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
- Cannot create table as it already exists
- Cannot create table as the namespace does not exist
- Altering a view is not supported by catalog:
- Altering a view is not supported by catalog
- Altering a view is not supported by catalog
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/9cf59c0e7f399b43.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java:267
}
}
@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, !cacheEnabled);
} 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)