apache/iceberg · error · NoSuchTableException

NoSuchTableException(ident)

Error message

NoSuchTableException(ident)

What it means

Thrown by SparkSessionCatalog.stageReplace when a REPLACE TABLE (via Spark session catalog) attempts to drop the existing table and the drop fails because the table does not exist. The catalog requires the target table to already exist for a replace operation; the underlying delegate catalog's dropTable(ident) returned false.

Source

Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/SparkSessionCatalog.java:235

  @Override
  public StagedTable stageReplace(
      Identifier ident, StructType schema, Transform[] partitions, Map<String, String> properties)
      throws NoSuchNamespaceException, NoSuchTableException {
    String provider = properties.get("provider");
    TableCatalog catalog;
    if (useIceberg(provider)) {
      if (asStagingCatalog != null) {
        return asStagingCatalog.stageReplace(ident, schema, partitions, properties);
      }
      catalog = icebergCatalog;
    } else {
      catalog = getSessionCatalog();
    }

    // attempt to drop the table and fail if it doesn't exist
    if (!catalog.dropTable(ident)) {
      throw new NoSuchTableException(ident);
    }

    try {
      // create the table with the session catalog, then wrap it in a staged table that will delete
      // to roll back
      Table table = catalog.createTable(ident, schema, partitions, properties);
      return new RollbackStagedTable(catalog, ident, table);

    } catch (TableAlreadyExistsException e) {
      // the table was deleted, but now already exists again. retry the replace.
      return stageReplace(ident, schema, partitions, properties);
    }
  }

  @Override
  public StagedTable stageCreateOrReplace(
      Identifier ident, StructType schema, Transform[] partitions, Map<String, String> properties)
      throws NoSuchNamespaceException {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Verify the table exists in the intended catalog: SHOW TABLES IN <catalog>.<namespace> and check the fully qualified identifier.
  2. Use CREATE TABLE instead of REPLACE TABLE if the table is not supposed to exist yet.
  3. Qualify the identifier with the correct catalog name so Spark routes the replace to the catalog that owns the table.

Example fix

// before
REPLACE TABLE prod.db.metrics USING iceberg AS SELECT ...
// after (table does not exist yet)
CREATE TABLE prod.db.metrics USING iceberg AS SELECT ...
Defensive patterns

Strategy: validation

Validate before calling

// Spark SQL
assert spark.catalog.tableExists("prod", "db", "metrics") : "table must exist before REPLACE TABLE";

Try / catch

try { spark.sql("REPLACE TABLE prod.db.metrics USING iceberg AS SELECT ...") } catch (AnalysisException e) { if (e.getMessage().contains("no such table")) { /* create instead of replace */ } else throw e; }

Prevention

When it happens

Trigger: Calling REPLACE TABLE ... USING iceberg (or catalogIdentifier replaceTable staged path) through the Spark session catalog when the identifier does not resolve to an existing table in the delegate session catalog.

Common situations: Typos in table name or namespace; table exists in a different catalog (e.g. default session catalog vs iceberg catalog) than the one being replaced; table was dropped concurrently by another job.

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