apache/iceberg · error · 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 MigrateTable, the source table is renamed to a backup identifier. If a table already exists under that backup name, the catalyst TableAlreadyExistsException is translated to AlreadyExistsException with this message, aborting the migration before any destructive change.

Solutions

  1. Drop or rename the existing backup table before re-running the migration
  2. Choose a different source table name or ensure the backup suffix doesn't collide
  3. If the backup table is from an earlier failed run, restore it or delete it after inspection

Example fix

// before
spark.sql("MIGRATE TO catalog.db.my_table"); // db.my_table_BACKUP_<ts> exists
// after
spark.sql("DROP TABLE IF EXISTS catalog.db.my_table_BACKUP_<old_ts>");
spark.sql("MIGRATE TO catalog.db.my_table");
Defensive patterns

Strategy: validation

Validate before calling

String backup = sourceIdent.name() + "_BACKUP_" + ...; // compute backup ident
if (catalog.tableExists(backupIdent)) { /* drop or pick new backup name first */ }

Try / catch

try { action.execute(); } catch (AlreadyExistsException e) { /* drop stale backup table, then retry */ }

Prevention

When it happens

Trigger: Running migrateTable when the computed backup identifier (source name suffixed with BACKUP_TABLE_SUFFIX, e.g. 'table_BACKUP_') already exists in the destination catalog, often from a prior failed/interrupted migration.

Common situations: Re-running a migration that previously failed midway and left the backup table; a pre-existing user table colliding with the backup naming 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/9a330f2a852c9c3a. Report an issue: GitHub.

Appendix: source

Thrown at spark/v4.1/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)