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
- Drop or rename the leftover backup table, restore it if needed, then re-run MIGRATE
- If the backup is the migrated result of a previous run, restore the source from the backup instead of migrating again
- 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
- After failed MIGRATE runs, check for and resolve leftover backup tables before retrying
- Restore the source from a backup only after verifying its contents
- Avoid running MIGRATE twice concurrently on the same source
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
- Cannot find source table
- Cannot find source table
- Cannot move view between catalogs: from=
- Cannot move view between catalogs: from=
- Cannot move view between catalogs: from=
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)