apache/iceberg · error · NoSuchTableException

Cannot find source table

Error message

Cannot find source table %s

What it means

MigrateTableSparkAction's renameAndBackupSourceTable fails when renaming the original table to its backup identifier because Spark reports the source table no longer exists (NoSuchTableException), wrapped as an Iceberg NoSuchTableException.

Solutions

  1. Check whether the backup table (e.g. db.tbl_BACKUP__) exists; if so restore it or drop it before re-running
  2. Confirm the source table still exists with SHOW TABLES / DESCRIBE TABLE in the source catalog
  3. Verify you are targeting the correct catalog (spark.sql.catalog settings) and the exact identifier
  4. Re-run the migration only after the source table is present and no backup name collision exists

Example fix

// after a failed run where db.tbl_BACKUP__ exists
spark.sql("ALTER TABLE db.tbl_BACKUP__ RENAME TO db.tbl"); // restore source
SparkActions.get(spark).migrateTable("db.tbl").execute();
Defensive patterns

Strategy: validation

Validate before calling

if (!spark.catalog().tableExists(sourceIdent)) { throw new IllegalStateException("source table missing"); }
if (spark.catalog().tableExists(backupIdent)) { restoreOrDropBackupFirst(); }

Try / catch

try { action.execute(); } catch (NoSuchTableException e) { /* verify/restore source and backup state, then re-run */ }

Prevention

When it happens

Trigger: doExecute -> renameAndBackupSourceTable: destCatalog().renameTable(sourceTableIdent, backupIdent) when the source table has disappeared (or the identifier resolves differently) between load and rename — e.g. a concurrent drop, or the source table was already renamed to the backup name in a prior failed run.

Common situations: Re-running a failed migration where the source was already renamed as backup; another job/user dropped the table mid-migration; wrong catalog/table identifier casing.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/4ac7782b60d8c741. Report an issue: GitHub.

Appendix: source

Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/actions/MigrateTableSparkAction.java:239

  @Override
  protected TableCatalog checkSourceCatalog(CatalogPlugin catalog) {
    // currently the import code relies on being able to look up the table in the session catalog
    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) {

View on GitHub (pinned to 86d9c8fc54)