apache/iceberg · error · RuntimeException

Couldn't load table '%s' in catalog '%s'

Error message

Couldn't load table '%s' in catalog '%s'

What it means

BaseProcedure.loadSparkTable resolves a table identifier through the given Spark catalog and expects an Iceberg SparkTable. If SparkV2Catalog.lookupTable throws NoSuchTableException, the procedure wraps it in a RuntimeException with the table identifier and catalog name. It signals that the procedure's target table could not be resolved at all.

Source

Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/procedures/BaseProcedure.java:175

    Preconditions.checkArgument(
        identifierAsString != null && !identifierAsString.isEmpty(),
        "Cannot handle an empty identifier for argument %s",
        argName);

    return Spark3Util.catalogAndIdentifier(
        "identifier for arg " + argName, spark, identifierAsString, catalog);
  }

  protected SparkTable loadSparkTable(Identifier ident) {
    try {
      Table table = tableCatalog.loadTable(ident);
      ValidationException.check(
          table instanceof SparkTable, "%s is not %s", ident, SparkTable.class.getName());
      return (SparkTable) table;
    } catch (NoSuchTableException e) {
      String errMsg =
          String.format("Couldn't load table '%s' in catalog '%s'", ident, tableCatalog.name());
      throw new RuntimeException(errMsg, e);
    }
  }

  protected Dataset<Row> loadRows(Identifier tableIdent, Map<String, String> options) {
    String tableName = Spark3Util.quotedFullIdentifier(tableCatalog().name(), tableIdent);
    return spark().read().options(options).table(tableName);
  }

  protected void refreshSparkCache(Identifier ident, Table table) {
    CacheManager cacheManager = spark.sharedState().cacheManager();
    DataSourceV2Relation relation =
        DataSourceV2Relation.create(table, Option.apply(tableCatalog), Option.apply(ident));
    cacheManager.recacheByPlan(spark, relation);
  }

  protected Expression filterExpression(Identifier ident, String where) {
    try {
      String name = Spark3Util.quotedFullIdentifier(tableCatalog.name(), ident);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Verify the identifier exists: SHOW TABLES IN <catalog>.<db> and confirm exact spelling/case.
  2. Qualify the name fully with the Iceberg catalog: catalog.namespace.table (use backticks for special chars).
  3. Check spark.sql.catalog.<name> configuration points at the Iceberg catalog implementation.
  4. If you control the code, catch the thrown RuntimeException and surface the NoSuchTableException cause.

Example fix

-- before
CALL iceberg.system.rewrite_data_files(table => 'db1.tbl');
-- after (correct catalog + case)
CALL iceberg.system.rewrite_data_files(table => 'my_db.my_table');
Defensive patterns

Strategy: try-catch

Validate before calling

SHOW TABLES IN catalog.db; -- or spark.catalog.tableExists("catalog.db.table") in Scala

Try / catch

try { procedureCall(...); } catch (RuntimeException e) { if (e.getCause() instanceof NoSuchTableException) { /* handle missing table */ } else throw e; }

Prevention

When it happens

Trigger: Calling a procedure such as rewrite_data_files(table => '...') or remove_orphan_files with an identifier that doesn't exist, is a view, is misqualified (wrong catalog/database), or whose case doesn't match the catalog's lookup rules.

Common situations: Typos in the qualified name; using a Spark session catalog name that isn't registered; the table exists in another catalog (e.g. spark_catalog vs iceberg catalog); pointing at a path-based identifier without proper quoting.

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