apache/iceberg · error · RuntimeException

Couldn't load table '${ident}' in catalog '${tableCatalog.na

Error message

Couldn't load table '${ident}' in catalog '${tableCatalog.name()}'

What it means

BaseProcedure.loadSparkTable catches Spark's NoSuchTableException when a procedure resolves its `table` argument and rethrows it as a RuntimeException stating the table could not be loaded in the given catalog. It means the procedure's table identifier was not resolvable — wrong name, wrong catalog, or the table is absent.

Source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/procedures/BaseProcedure.java:159

    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 correct the `table` argument.
  2. Fully qualify with catalog and namespace: `catalog.db.table`.
  3. Check the active catalog (`SELECT current_catalog()`) or `USE catalog.db` before invoking.
  4. Catch the RuntimeException in orchestration and handle absent tables gracefully.

Example fix

// before
CALL iceberg.system.rewrite_data_files(table => 'mytable')
// after
CALL iceberg.system.rewrite_data_files(table => 'iceberg_catalog.db.mytable')
Defensive patterns

Strategy: try-catch

Validate before calling

boolean exists = spark.sql("SHOW TABLES IN " + catalog + "." + db).collectAsList().stream()
    .anyMatch(r -> r.getAs("tableName").toString().equalsIgnoreCase(table));
if (!exists) throw new IllegalArgumentException("Table not found: " + catalog + "." + db + "." + table);

Try / catch

try { spark.sql("CALL cat.system.rewrite_data_files(table => 'cat.db.t')"); } catch (RuntimeException e) { if (e.getMessage() != null && e.getMessage().startsWith("Couldn't load table")) { /* fix identifier or handle absence */ } throw e; }

Prevention

When it happens

Trigger: Invoking any Iceberg Spark procedure (rewrite_data_files, expire_snapshots, remove_orphan_files, publish_changes, etc.) with `table => 'wrong_or_missing_name'` or an identifier that resolves in a different catalog.

Common situations: Typos in the table name; unqualified names resolving against the session catalog instead of the Iceberg catalog; case sensitivity mismatches; the table dropped by a concurrent job before the procedure ran.

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