apache/iceberg · error · NoSuchTableException

Cannot find source table '%s'

Error message

Cannot find source table '%s'

What it means

BaseTableCreationSparkAction's constructor loads the source table from the given Spark catalog; if Spark reports NoSuchTableException, it is translated into Iceberg's NoSuchTableException 'Cannot find source table'. Thrown before any snapshot/clone action (e.g. snapshot, migrate, addFiles) starts.

Source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/actions/BaseTableCreationSparkAction.java:81

  private final String sourceTableLocation;
  private final TableCatalog sourceCatalog;
  private final Identifier sourceTableIdent;

  // Optional Parameters for destination
  private final Map<String, String> additionalProperties = Maps.newHashMap();

  BaseTableCreationSparkAction(
      SparkSession spark, CatalogPlugin sourceCatalog, Identifier sourceTableIdent) {
    super(spark);

    this.sourceCatalog = checkSourceCatalog(sourceCatalog);
    this.sourceTableIdent = sourceTableIdent;

    try {
      this.sourceTable = (V1Table) this.sourceCatalog.loadTable(sourceTableIdent);
      this.sourceCatalogTable = sourceTable.v1Table();
    } catch (org.apache.spark.sql.catalyst.analysis.NoSuchTableException e) {
      throw new NoSuchTableException("Cannot find source table '%s'", sourceTableIdent);
    } catch (ClassCastException e) {
      throw new IllegalArgumentException(
          String.format("Cannot use non-v1 table '%s' as a source", sourceTableIdent), e);
    }
    validateSourceTable();

    this.sourceTableLocation =
        CatalogUtils.URIToString(sourceCatalogTable.storage().locationUri().get());
  }

  protected abstract TableCatalog checkSourceCatalog(CatalogPlugin catalog);

  protected abstract StagingTableCatalog destCatalog();

  protected abstract Identifier destTableIdent();

  protected abstract Map<String, String> destTableProps();

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Verify the identifier exists: SHOW TABLES IN catalog.namespace
  2. Confirm the Spark session has the correct catalog configured (spark.sql.catalog.<name>)
  3. Check for typos and exact case of namespace and table names

Example fix

// before
SparkActions.get(spark).snapshot("prod", "sales.fact", "iceberg.ns.fact").execute();
// after — verify identifier first
spark.sql("SHOW TABLES IN prod.sales");
SparkActions.get(spark).snapshot("prod", "sales.facts", "iceberg.ns.fact").execute();
Defensive patterns

Strategy: validation

Validate before calling

Dataset<Row> check = spark.sql("SHOW TABLES IN " + catalog + "." + namespace);
boolean exists = check.collectAsList().stream().anyMatch(r -> r.getString(1).equalsIgnoreCase(table));
if (!exists) throw new IllegalArgumentException("Source table not found: " + ident);

Type guard

boolean sourceExists(SparkSession spark, String catalog, String ns, String tbl) { return !spark.sql(String.format("SHOW TABLES IN %s.%s", catalog, ns)).filter("tableName = '" + tbl + "'").isEmpty(); }

Try / catch

try { action.execute(); } catch (NoSuchTableException e) { throw new IllegalArgumentException("Verify source identifier: " + e.getMessage(), e); }

Prevention

When it happens

Trigger: Calling SparkActions.snapshot("catalog", "ns.dest", ...) or migrate with a source table identifier that does not exist in the source catalog.

Common situations: Typo in table or namespace name; wrong catalog name in a multi-catalog session; table dropped between planning and execution; case-sensitive identifier mismatch.

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