apache/iceberg · error · org.apache.spark.sql.catalyst.analysis.NoSuchTableException

No such table: %s

Error message

No such table: %s

What it means

SparkCachedTableCatalog.load() looks up the table key in TABLE_CACHE and throws NoSuchTableException when the key is absent. Unlike SparkCatalog, this catalog does not reach out to a backing catalog; it can only serve what has already been cached, so any cache miss surfaces as 'No such table'.

Source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/SparkCachedTableCatalog.java:142

  }

  @Override
  public String name() {
    return name;
  }

  private SparkTable load(Identifier ident) throws NoSuchTableException {
    Preconditions.checkArgument(
        ident.namespace().length == 0, CLASS_NAME + " does not support namespaces");

    Pair<String, List<String>> parsedIdent = parseIdent(ident);
    String key = parsedIdent.first();
    TableLoadOptions options = parseLoadOptions(parsedIdent.second());

    Table table = TABLE_CACHE.get(key);

    if (table == null) {
      throw new NoSuchTableException(ident);
    }

    if (options.isTableRewrite()) {
      return new SparkTable(table, null, false, true);
    }

    if (options.snapshotId() != null) {
      return new SparkTable(table, options.snapshotId(), false);
    } else if (options.asOfTimestamp() != null) {
      return new SparkTable(
          table, SnapshotUtil.snapshotIdAsOfTime(table, options.asOfTimestamp()), false);
    } else if (options.branch() != null) {
      Snapshot branchSnapshot = table.snapshot(options.branch());
      Preconditions.checkArgument(
          branchSnapshot != null,
          "Cannot find snapshot associated with branch name: %s",
          options.branch());
      return new SparkTable(table, branchSnapshot.snapshotId(), false);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Load/refresh the table through the real catalog first so the entry is populated in TABLE_CACHE, then query via the cached catalog.
  2. Verify the identifier exactly matches the key used at registration (namespace and table name).
  3. Check whether tableExists(ident) returns true before loading to fail fast.
  4. If the table is truly persistent, use SparkCatalog instead of SparkCachedTableCatalog.

Example fix

// before
SparkTable t = cachedCatalog.loadTable(Identifier.of(new String[]{"db"}, "t")); // cache miss

// after
if (cachedCatalog.tableExists(Identifier.of(new String[]{"db"}, "t"))) {
  SparkTable t = cachedCatalog.loadTable(Identifier.of(new String[]{"db"}, "t"));
} else {
  spark.sql("SELECT * FROM spark_catalog.db.t"); // populates cache via real catalog
}
Defensive patterns

Strategy: try-catch

Validate before calling

Identifier ident = Identifier.of(namespace, name);
if (!cachedCatalog.tableExists(ident)) {
  // refresh cache via real catalog before loading
  spark.table("spark_catalog." + String.join(".", namespace) + "." + name);
}

Type guard

boolean isCached = key != null && cachedCatalog.tableExists(Identifier.of(new String[]{key}, tableName));

Try / catch

try {
  SparkTable t = cachedCatalog.loadTable(ident);
} catch (org.apache.spark.sql.catalyst.analysis.NoSuchTableException e) {
  // re-register through the real catalog, then retry once
}

Prevention

When it happens

Trigger: loadTable(ident) / table(ident) with an identifier whose first part (key) was never registered in the cache; the cached entry was invalidated or the session that populated the cache was recreated; a typo'd namespace in the identifier.

Common situations: Querying a cached table from a new SparkSession without re-registering it; referencing the table after cache eviction; case-sensitivity/key-format mismatch between how the table was cached and how it is loaded.

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