apache/iceberg · error · AlreadyExistsException
Table already exists: %s
Error message
Table already exists: %s
What it means
JdbcCatalog.renameTable throws AlreadyExistsException when the target table identifier already exists as a table. The check runs before the UPDATE so an existing destination table is never overwritten. It is a pre-flight guard in addition to the database primary-key constraint check that follows.
Source
Thrown at core/src/main/java/org/apache/iceberg/jdbc/JdbcCatalog.java:373
public void renameTable(TableIdentifier from, TableIdentifier to) {
if (from.equals(to)) {
return;
}
if (!tableExists(from)) {
throw new NoSuchTableException("Table does not exist: %s", from);
}
if (!namespaceExists(to.namespace())) {
throw new NoSuchNamespaceException("Namespace does not exist: %s", to.namespace());
}
if (schemaVersion == JdbcUtil.SchemaVersion.V1 && viewExists(to)) {
throw new AlreadyExistsException("Cannot rename %s to %s. View already exists", from, to);
}
if (tableExists(to)) {
throw new AlreadyExistsException("Table already exists: %s", to);
}
int updatedRecords =
execute(
err -> {
if (JdbcUtil.isConstraintViolation(err)) {
throw new AlreadyExistsException("Table already exists: %s", to);
}
},
(schemaVersion == JdbcUtil.SchemaVersion.V1)
? JdbcUtil.V1_RENAME_TABLE_SQL
: JdbcUtil.V0_RENAME_TABLE_SQL,
JdbcUtil.namespaceToString(to.namespace()),
to.name(),
catalogName,
JdbcUtil.namespaceToString(from.namespace()),
from.name());
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Use a different target name or drop the existing table at the target first
- Check catalog.tableExists(to) before issuing the rename
- Handle AlreadyExistsException in the caller and treat it as idempotent success if the rename already completed
Example fix
// before
catalog.renameTable(from, to); // may throw
// after
if (!catalog.tableExists(to)) {
catalog.renameTable(from, to);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (catalog.tableExists(to)) { throw new IllegalStateException("target table exists"); } Type guard
boolean targetFree = !catalog.tableExists(to);
Try / catch
try { catalog.renameTable(from, to); } catch (AlreadyExistsException e) { /* target occupied: choose another name or drop first */ } Prevention
- Always probe tableExists(to) before renameTable
- Make rename pipelines idempotent: treat AlreadyExistsException after a retry as success
- Use unique target names (suffixes/timestamps) in concurrent workflows
When it happens
Trigger: Calling catalog.renameTable(from, to) where catalog.tableExists(to) is true — i.e. a table with the same namespace and name as 'to' already exists.
Common situations: Retrying a rename after a previous partial rename; scripted pipelines that re-run against an already-renamed catalog; two clients renaming concurrently to the same target name.
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 rename %s to %s. View already exists
- Cannot rename table %s to %s: %s already exists
- Namespace already exists: %s
- Cannot rename %s to %s. Table already exists
- Cannot rename %s to %s. View already exists
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/e4c5a9116335234a.
Report an issue: GitHub.