apache/iceberg · error · org.apache.iceberg.exceptions.AlreadyExistsException

Cannot rename as for backup. The backup table already…

Error message

Cannot rename %s as %s for backup. The backup table already exists.

What it means

During MIGRATE, the source table is renamed to a backup name before the new Iceberg table is created. If a table already exists under the backup identifier, destCatalog().renameTable throws TableAlreadyExistsException, converted into this AlreadyExistsException. The migration aborts rather than overwriting the backup.

Solutions

  1. Drop or rename the leftover backup table, restore it if needed, then re-run MIGRATE
  2. If the backup is the migrated result of a previous run, restore the source from the backup instead of migrating again
  3. Pick a source identifier that yields a unique backup name

Example fix

// before
CALL iceberg.system.migrate('db.src_tbl') -- backup db.SRC_TBL_BACKUP__... exists
// after
DROP TABLE db.src_tbl_backup; -- after verifying it is disposable
CALL iceberg.system.migrate('db.src_tbl');
Defensive patterns

Strategy: validation

Validate before calling

// Check for leftover backup tables before re-running MIGRATE
spark.sql("SHOW TABLES IN db LIKE '*BACKUP*'");

Try / catch

try { migrateAction.execute(); } catch (AlreadyExistsException e) { /* inspect and remove/restore the existing backup table, then retry */ }

Prevention

When it happens

Trigger: Running MIGRATE when a table with the auto-generated (or previously used) backup identifier already exists in the destination catalog, e.g. from an earlier failed/aborted migrate run.

Common situations: Re-running MIGRATE after a previous failure left the backup table in place; another table happens to share the backup name pattern.

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

Appendix: source

Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/actions/MigrateTableSparkAction.java:242

    Preconditions.checkArgument(
        catalog instanceof SparkSessionCatalog,
        "Cannot migrate a table from a non-Iceberg Spark Session Catalog. Found %s of class %s as the source catalog.",
        catalog.name(),
        catalog.getClass().getName());

    return (TableCatalog) catalog;
  }

  private void renameAndBackupSourceTable() {
    try {
      LOG.info("Renaming {} as {} for backup", sourceTableIdent(), backupIdent);
      destCatalog().renameTable(sourceTableIdent(), backupIdent);

    } catch (org.apache.spark.sql.catalyst.analysis.NoSuchTableException e) {
      throw new NoSuchTableException("Cannot find source table %s", sourceTableIdent());

    } catch (org.apache.spark.sql.catalyst.analysis.TableAlreadyExistsException e) {
      throw new AlreadyExistsException(
          "Cannot rename %s as %s for backup. The backup table already exists.",
          sourceTableIdent(), backupIdent);
    }
  }

  private void restoreSourceTable() {
    try {
      LOG.info("Restoring {} from {}", sourceTableIdent(), backupIdent);
      destCatalog().renameTable(backupIdent, sourceTableIdent());

    } catch (org.apache.spark.sql.catalyst.analysis.NoSuchTableException e) {
      LOG.error(
          "Cannot restore the original table, the backup table {} cannot be found", backupIdent, e);

    } catch (org.apache.spark.sql.catalyst.analysis.TableAlreadyExistsException e) {
      LOG.error(
          "Cannot restore the original table, a table with the original name exists. "
              + "Use the backup table {} to restore the original table manually.",

View on GitHub (pinned to 86d9c8fc54)