apache/iceberg · error · org.apache.spark.sql.catalyst.analysis.TableAlreadyExistsException
TableAlreadyExistsException
Error message
TableAlreadyExistsException: <to>
What it means
When the rename target identifier already exists, the Iceberg catalog throws AlreadyExistsException and SparkCatalog translates it to Spark's TableAlreadyExistsException for the target name. Renames in Iceberg catalogs are fail-fast and never overwrite an existing table.
Solutions
- Drop or rename the existing target table first
- Choose a unique target name (e.g. append a timestamp)
- Check for the target's existence before renaming
- Handle TableAlreadyExistsException and skip the rename on retries
Example fix
// before
spark.sql("ALTER TABLE db.t RENAME TO db.archive") // db.archive exists
// after
spark.sql("ALTER TABLE db.t RENAME TO db.archive_" + System.currentTimeMillis()) Defensive patterns
Strategy: validation
Validate before calling
if (spark.catalog().tableExists(toIdent)) { throw new IllegalStateException("target already exists"); } Try / catch
try { spark.sql("ALTER TABLE db.t RENAME TO db.t2"); } catch (TableAlreadyExistsException e) { /* pick another target or skip */ } Prevention
- Generate unique target names (timestamp/uuid suffix)
- Check target existence before renaming
- Handle retries by treating AlreadyExists as success
When it happens
Trigger: ALTER TABLE ... RENAME TO where the destination table already exists in the same namespace; retrying a rename that partially appeared to succeed.
Common situations: Job retries re-attempting a completed rename; staging table naming collisions; automated pipelines generating deterministic target names.
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
- TableAlreadyExistsException(to)
- View already exists: toIdentifier
- View already exists
- ViewAlreadyExistsException(toIdentifier)
- Cannot create table as it already exists
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/118b08b9085bd1f8.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java:383
private boolean catalogDropTable(Identifier ident) {
if (isPathIdentifier(ident)) {
return tables.dropTable(((PathIdentifier) ident).location(), false /* don't purge data */);
} else {
return icebergCatalog.dropTable(buildIdentifier(ident), false /* don't purge data */);
}
}
@Override
public void renameTable(Identifier from, Identifier to)
throws NoSuchTableException, TableAlreadyExistsException {
try {
checkNotPathIdentifier(from, "renameTable");
checkNotPathIdentifier(to, "renameTable");
icebergCatalog.renameTable(buildIdentifier(from), buildIdentifier(to));
} catch (org.apache.iceberg.exceptions.NoSuchTableException e) {
throw new NoSuchTableException(from);
} catch (AlreadyExistsException e) {
throw new TableAlreadyExistsException(to);
}
}
@Override
public void invalidateTable(Identifier ident) {
if (!isPathIdentifier(ident)) {
icebergCatalog.invalidateTable(buildIdentifier(ident));
}
}
@Override
public Identifier[] listTables(String[] namespace) {
return icebergCatalog.listTables(Namespace.of(namespace)).stream()
.map(ident -> Identifier.of(ident.namespace().levels(), ident.name()))
.toArray(Identifier[]::new);
}
@OverrideView on GitHub (pinned to 86d9c8fc54)