apache/iceberg · error · AlreadyExistsException

Table already exists: %s

Error message

Table already exists: %s

What it means

Thrown when the Hive Metastore rejects a rename with InvalidOperationException whose message contains 'new table <to> already exists'. Iceberg converts this into AlreadyExistsException, the catalog API's signal that the destination identifier is already taken. The source table/view is unchanged.

Source

Thrown at hive-metastore/src/main/java/org/apache/iceberg/hive/HiveCatalog.java:443

          client -> {
            MetastoreUtil.alterTable(client, fromDatabase, fromName, table);
            return null;
          });

      LOG.info("Renamed {} from {}, to {}", contentType.value(), from, to);

    } catch (NoSuchObjectException e) {
      switch (contentType) {
        case TABLE:
          throw new NoSuchTableException("Cannot rename %s to %s. Table does not exist", from, to);
        case VIEW:
          throw new NoSuchViewException("Cannot rename %s to %s. View does not exist", from, to);
      }

    } catch (InvalidOperationException e) {
      if (e.getMessage() != null
          && e.getMessage().contains(String.format("new table %s already exists", to))) {
        throw new AlreadyExistsException("Table already exists: %s", to);
      } else {
        throw new RuntimeException("Failed to rename " + from + " to " + to, e);
      }

    } catch (TException e) {
      throw new RuntimeException("Failed to rename " + from + " to " + to, e);

    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      throw new RuntimeException("Interrupted in call to rename", e);
    }
  }

  private void validateTableIsIcebergTableOrView(
      HiveOperationsBase.ContentType contentType, Table table, String fullName) {
    switch (contentType) {
      case TABLE:
        HiveOperationsBase.validateTableIsIceberg(table, fullName);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Check catalog.tableExists(to) first and choose a unique destination name.
  2. Drop or rename the existing destination table if it is stale/unwanted.
  3. Make migration scripts idempotent: skip the rename when the target already exists and the source is gone.

Example fix

// before
catalog.renameTable(from, to);
// after
if (!catalog.tableExists(to)) {
  catalog.renameTable(from, to);
}
Defensive patterns

Strategy: validation

Validate before calling

if (catalog.tableExists(to)) { throw new IllegalArgumentException("Destination " + to + " already exists"); }

Try / catch

try { catalog.renameTable(from, to); } catch (org.apache.iceberg.exceptions.AlreadyExistsException e) { LOG.error("Destination {} already exists", to, e); }

Prevention

When it happens

Trigger: Calling renameTable or renameView with a destination identifier 'to' that already exists as a table in the same Hive database.

Common situations: Renaming to a name that a previous partial run already created; two jobs renaming concurrently to the same target; re-running a non-idempotent migration script.

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/10acdb604a5d42d5. Report an issue: GitHub.