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

  1. Use a different target name or drop the existing table at the target first
  2. Check catalog.tableExists(to) before issuing the rename
  3. 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

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/e4c5a9116335234a. Report an issue: GitHub.