apache/iceberg · error · TableAlreadyExistsException
org.apache.iceberg.exceptions.AlreadyExistsException:
Error message
org.apache.iceberg.exceptions.AlreadyExistsException:
What it means
SparkCatalog.createTable maps Iceberg's AlreadyExistsException (raised by the underlying catalog's TableBuilder.create() because an identifier or location already exists) to Spark's TableAlreadyExistsException. Spark raises it to the user as a TABLE_OR_VIEW_ALREADY_EXISTS-style failure.
Source
Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java:268
}
}
@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)
Solutions
- Use CREATE TABLE IF NOT EXISTS or stageCreateOrReplace semantics if replacement is intended.
- Check tableExists(ident) before creating in code that must be idempotent.
- If a different table legitimately occupies the location, choose a new location or drop the conflicting table first.
- Handle TableAlreadyExistsException in the caller when racing concurrent creates.
Example fix
// before
spark.sql("CREATE TABLE prod.db.events (id BIGINT) USING iceberg");
// after
spark.sql("CREATE TABLE IF NOT EXISTS prod.db.events (id BIGINT) USING iceberg"); Defensive patterns
Strategy: try-catch
Validate before calling
if (catalog.tableExists(ident)) {
throw new IllegalArgumentException("Table already exists: " + ident);
} Try / catch
try {
spark.sql(createTableSql);
} catch (TableAlreadyExistsException e) {
LOG.warn("Table {} already exists, skipping create", ident);
return spark.table(ident.toString());
} Prevention
- Use CREATE TABLE IF NOT EXISTS for idempotent DDL.
- Pre-check tableExists before programmatic createTable.
- Serialize concurrent create jobs or use unique names.
- Remember the custom 'location' can also collide with another table.
When it happens
Trigger: CREATE TABLE catalog.db.name ... when the table already exists in the catalog, or when another table is already registered at the requested custom location.
Common situations: Re-running idempotent-looking DDL scripts; races between concurrent Spark jobs creating the same table; stale catalog metadata in V2 session catalogs.
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 %s as it already exists
- Unsupported table change: setting unique key constraints.
- Unsupported format in USING: ${provider}
- Cannot add column %s since setting default values in Spark i
- SparkCachedTableCatalog does not support creating tables
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/86efe2a498e19b7e.
Report an issue: GitHub.