apache/iceberg · error · TableAlreadyExistException

TableAlreadyExistException

Error message

TableAlreadyExistException

What it means

Thrown by FlinkCatalog.renameTable when the target table name already exists in the Iceberg catalog (AlreadyExistsException), wrapped into Flink's TableAlreadyExistException. Iceberg's rename does not overwrite existing targets.

Solutions

  1. Choose a target name that does not already exist, or drop/rename the existing target first.
  2. Check tableExists on the target ObjectPath before renaming.
  3. Catch TableAlreadyExistException and handle the collision in application logic.

Example fix

// before
flinkCatalog.renameTable(new ObjectPath("db", "old"), "existing", false);
// after
ObjectPath target = new ObjectPath("db", "existing");
if (!flinkCatalog.tableExists(target)) {
  flinkCatalog.renameTable(new ObjectPath("db", "old"), "existing", false);
}
Defensive patterns

Strategy: validation

Validate before calling

ObjectPath target = new ObjectPath(db, newName);
if (flinkCatalog.tableExists(target)) { throw new IllegalStateException("target exists: " + target); }

Try / catch

try {
  flinkCatalog.renameTable(tablePath, newName, false);
} catch (TableAlreadyExistException e) {
  // resolve collision: pick a new name or archive existing target
}

Prevention

When it happens

Trigger: Calling renameTable to a newTableName that already exists in the same database, with no pre-check.

Common situations: Retrying a partially completed rename; automated jobs generating colliding target names (e.g. timestamped names that already exist); attempting to swap tables by renaming over an existing one.

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

Appendix: source

Thrown at flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/FlinkCatalog.java:408

      if (!ignoreIfNotExists) {
        throw new TableNotExistException(getName(), tablePath, e);
      }
    }
  }

  @Override
  public void renameTable(ObjectPath tablePath, String newTableName, boolean ignoreIfNotExists)
      throws TableNotExistException, TableAlreadyExistException, CatalogException {
    try {
      icebergCatalog.renameTable(
          toIdentifier(tablePath),
          toIdentifier(new ObjectPath(tablePath.getDatabaseName(), newTableName)));
    } catch (org.apache.iceberg.exceptions.NoSuchTableException e) {
      if (!ignoreIfNotExists) {
        throw new TableNotExistException(getName(), tablePath, e);
      }
    } catch (AlreadyExistsException e) {
      throw new TableAlreadyExistException(getName(), tablePath, e);
    }
  }

  @Override
  public void createTable(ObjectPath tablePath, CatalogBaseTable table, boolean ignoreIfExists)
      throws CatalogException, TableAlreadyExistException {
    // Creating Iceberg table using connector is allowed only when table is created using LIKE
    if (Objects.equals(
            table.getOptions().get(FlinkCreateTableOptions.CONNECTOR_PROPS_KEY),
            FlinkDynamicTableFactory.FACTORY_IDENTIFIER)
        && table.getOptions().get(FlinkCreateTableOptions.SRC_CATALOG_PROPS_KEY) == null) {
      throw new IllegalArgumentException(
          "Cannot create the table with 'connector'='iceberg' table property in "
              + "an iceberg catalog, Please create table with 'connector'='iceberg' property in a non-iceberg catalog or "
              + "create table without 'connector'='iceberg' related properties in an iceberg table.");
    }

    Preconditions.checkArgument(

View on GitHub (pinned to 86d9c8fc54)