apache/iceberg · error · NoSuchTableException
NoSuchTableException(ident)
Error message
NoSuchTableException(ident)
What it means
Spark's NoSuchTableException thrown from the load path when the identifier has an empty namespace and the Iceberg catalog reports no table. Because there is no namespace to reinterpret as a table identifier (snapshot-selector fallback), Spark immediately surfaces the original failure as NoSuchTableException for the identifier.
Source
Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java:941
if (identifier instanceof PathIdentifier) {
throw new IllegalArgumentException(
String.format(
"Cannot pass path based identifier to %s method. %s is a path.", method, identifier));
}
}
private Table load(Identifier ident, TimeTravel timeTravel) throws NoSuchTableException {
if (isPathIdentifier(ident)) {
return loadPath((PathIdentifier) ident, timeTravel);
}
try {
org.apache.iceberg.Table table = icebergCatalog.loadTable(buildIdentifier(ident));
return SparkTable.create(table, timeTravel);
} catch (org.apache.iceberg.exceptions.NoSuchTableException e) {
if (ident.namespace().length == 0) {
throw new NoSuchTableException(ident);
}
// if the original load didn't work, try using the namespace as an identifier because
// the original identifier may include a snapshot selector or may point to the changelog
TableIdentifier namespaceAsIdent = buildIdentifier(namespaceToIdentifier(ident.namespace()));
org.apache.iceberg.Table table;
try {
table = icebergCatalog.loadTable(namespaceAsIdent);
} catch (Exception ignored) {
// the namespace does not identify a table, so it cannot be a table with a snapshot selector
// throw an exception for the original identifier
throw new NoSuchTableException(ident);
}
// loading the namespace as a table worked, check the name to see if it is a valid selector
// or if the name points to the changelog
if (ident.name().equalsIgnoreCase(SparkChangelogTable.TABLE_NAME)) {View on GitHub (pinned to 86d9c8fc54)
Solutions
- Qualify the table with its namespace: USE db; or SELECT * FROM catalog.db.table
- Verify the table exists with SHOW TABLES IN catalog.db
- Check the spark.sql.catalog.<name> wiring points at the intended warehouse
- Set the session catalog/current namespace so single-part names resolve
Example fix
// before SELECT * FROM local.events; // no namespace, table not found // after SELECT * FROM local.db.events;
Defensive patterns
Strategy: validation
Validate before calling
if (ident.namespace().length == 0 || !spark.catalog().tableExists(ident.namespace(), ident.name())) { /* qualify or fix the name */ } Try / catch
try {
Table t = catalog.loadTable(ident);
} catch (NoSuchTableException e) {
// use a namespace-qualified identifier
} Prevention
- Always use fully-qualified catalog.namespace.table names
- USE the namespace or set currentNamespace before single-part queries
- Verify table existence with SHOW TABLES after DDL
When it happens
Trigger: catalog.loadTable(Identifier of single name) where icebergCatalog.loadTable throws NoSuchTableException and ident.namespace().length == 0 — i.e., referencing just 'tablename' with no database and no such table at the catalog root.
Common situations: Forgetting the database/namespace qualifier; using the wrong catalog name in spark.sql.catalog config; table dropped or never created; current namespace not set in the session.
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
- Table does not exist: ident
- Table does not exist: %s
- Table does not exist: %s
- No such table '%s' in '%s'
- No such table '%s'
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/02e83bd493f3ac20.
Report an issue: GitHub.