apache/iceberg · error · org.apache.iceberg.exceptions.AlreadyExistsException
Cannot create table as it already exists
Error message
Cannot create table %s as it already exists
What it means
During staging of the destination table, destCatalog().stageCreate throws Spark's TableAlreadyExistsException when a table with the destination identifier already exists. The action converts it into Iceberg's AlreadyExistsException with this message.
Solutions
- Choose a unique destination table name
- Drop or rename the existing destination table before re-running the action
- If re-running after failure, remove the leftover staged table from the destination catalog
Example fix
// before
CALL iceberg.system.snapshot('source_tbl', 'db.existing_tbl')
// after
DROP TABLE db.existing_tbl; -- or pick a new name
CALL iceberg.system.snapshot('source_tbl', 'db.new_tbl'); Defensive patterns
Strategy: validation
Validate before calling
// Check destination does not exist before running
spark.sql("DESCRIBE TABLE db.dest_tbl"); // throws if absent -> safe to proceed Try / catch
try { ... } catch (AlreadyExistsException e) { /* pick a new name or drop existing table */ } Prevention
- Check table existence (DESCRIBE/SHOW TABLES) before choosing the destination name
- Clean up leftover staged/destination tables after failed migration runs
- Use unique, timestamped destination names for one-off migrations
When it happens
Trigger: Running MIGRATE or SNAPSHOT where the destination table name already exists in the destination catalog; re-running a previously failed/partial migrate after the destination was already created.
Common situations: Re-running a failed migration without cleaning up the staged destination table; accidentally reusing an existing table name; OR REPLACE not supported for this procedure path.
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 the namespace does not exist
- Table already exists
- 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/751a47128a279f00.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/actions/BaseTableCreationSparkAction.java:167
catalog.getClass().getName(),
SparkSessionCatalog.class.getName(),
SparkCatalog.class.getName());
return (StagingTableCatalog) catalog;
}
protected StagedSparkTable stageDestTable() {
try {
Map<String, String> props = destTableProps();
StructType schema = sourceTable.schema();
Transform[] partitioning = sourceTable.partitioning();
return (StagedSparkTable)
destCatalog().stageCreate(destTableIdent(), schema, partitioning, props);
} catch (org.apache.spark.sql.catalyst.analysis.NoSuchNamespaceException e) {
throw new NoSuchNamespaceException(
"Cannot create table %s as the namespace does not exist", destTableIdent());
} catch (org.apache.spark.sql.catalyst.analysis.TableAlreadyExistsException e) {
throw new AlreadyExistsException(
"Cannot create table %s as it already exists", destTableIdent());
}
}
protected void ensureNameMappingPresent(Table table) {
if (!table.properties().containsKey(TableProperties.DEFAULT_NAME_MAPPING)) {
NameMapping nameMapping = MappingUtil.create(table.schema());
String nameMappingJson = NameMappingParser.toJson(nameMapping);
table.updateProperties().set(TableProperties.DEFAULT_NAME_MAPPING, nameMappingJson).commit();
}
}
protected String getMetadataLocation(Table table) {
String defaultValue =
LocationUtil.stripTrailingSlash(table.location()) + "/" + ICEBERG_METADATA_FOLDER;
return LocationUtil.stripTrailingSlash(
table.properties().getOrDefault(TableProperties.WRITE_METADATA_LOCATION, defaultValue));
}View on GitHub (pinned to 86d9c8fc54)