apache/iceberg · error · NoSuchTableException

Cannot find source table %s

Error message

Cannot find source table %s

What it means

MigrateTableSparkAction backs up the source table by renaming it (destCatalog().renameTable(sourceTableIdent(), backupIdent)). Spark's catalog threw NoSuchTableException, so the action rethrows it as Iceberg's NoSuchTableException 'Cannot find source table %s' — the table you asked to migrate does not exist in the destination catalog.

Source

Thrown at spark/v3.5/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)

Solutions

  1. Verify the table exists: run SHOW TABLES IN <catalog>.<db> or spark.catalog.tableExists("catalog.db.table") with the exact identifier used in migrate().
  2. Check the identifier's case and case-sensitivity setting (spark.sql.caseSensitive) and quoting.
  3. Confirm the Spark session is configured for the catalog you expect (spark.sql.catalog.<name> entries) and that you are not silently hitting spark_default.
  4. Re-run the migration after creating/restoring the missing source table.

Example fix

// before
spark.sql("CALL prod_catalog.system.migrate(table => 'events')");
// after
spark.sql("CALL prod_catalog.system.migrate(table => 'analytics.events')"); // fully-qualified, verified via SHOW TABLES
Defensive patterns

Strategy: validation

Validate before calling

// Scala / SQL pre-check before migrate
val ident = "prod_catalog.analytics.events"
if (!spark.catalog.tableExists(ident))
  throw new IllegalArgumentException(s"Source table $ident does not exist")

Try / catch

try {
  SparkActions.get(spark).migrateTable(ident).execute();
} catch (org.apache.iceberg.exceptions.NoSuchTableException e) {
  LOG.error("Verify identifier '{}' exists in the target catalog", ident, e);
}

Prevention

When it happens

Trigger: CALL spark_catalog.system.migrate(...) or SparkActions.get(spark).migrateTable(ident) where the source identifier is misspelled, the table lives in a different catalog/database, or the catalog lookup fails before the migration starts.

Common situations: Wrong three-part identifier, running against the wrong Spark session/catalog config, case sensitivity mismatch (spark.sql.caseSensitive), or the table being dropped by another process just before migration.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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