apache/iceberg · error · NoSuchTableException
NoSuchTableException(from)
Error message
NoSuchTableException(from)
What it means
Spark's renameTable failed because the source table identifier could not be loaded by the underlying Iceberg catalog; the Iceberg NoSuchTableException was caught and rethrown as Spark's NoSuchTableException for the 'from' identifier. Renaming requires the source table to exist and be loadable at commit time.
Solutions
- Confirm the source table exists and is loadable via SELECT before renaming.
- Use the fully-qualified source name (catalog.namespace.table) to avoid resolution against the wrong catalog.
- Check for concurrent drops; coordinate rename with other jobs.
- If the metastore entry exists but loading fails, repair or re-register the table metadata location.
Example fix
// before
spark.sql("ALTER TABLE mydb.orders RENAME TO mydb.orders_v2") // NoSuchTableException: mydb.orders
// after
if (spark.catalog().tableExists("iceberg_catalog.mydb.orders")) {
spark.sql("ALTER TABLE iceberg_catalog.mydb.orders RENAME TO iceberg_catalog.mydb.orders_v2")
} else {
// handle missing source explicitly
} Defensive patterns
Strategy: validation
Validate before calling
if (!spark.catalog().tableExists("iceberg_catalog.mydb.orders")) {
throw new IllegalStateException("Rename source table does not exist");
} Try / catch
try {
catalog.renameTable(from, to);
} catch (NoSuchTableException e) {
// source missing: report e.getMessage() with the resolved identifier
} Prevention
- Verify the source exists immediately before rename
- Use fully-qualified source identifiers
- Avoid renaming tables managed by concurrent pipelines
- Re-register missing metadata before renaming migrated tables
When it happens
Trigger: Calling ALTER TABLE ... RENAME TO (or catalog.renameTable(from, to)) where buildIdentifier(from) does not resolve to an existing Iceberg table; the source was dropped concurrently; the 'from' identifier is qualified with the wrong catalog or namespace.
Common situations: Scripting RENAME operations where an earlier cleanup step already dropped the table; Hive-metastore-backed catalogs where the Hive table exists but the Iceberg metadata location is gone; passing an unqualified name while the table lives in another namespace.
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
- Cannot find source table
- Cannot find source table
- Cannot find source table
- Cannot move view between catalogs: from=
- Cannot rename to . Table does not exist
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/bf8999c11f539943.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java:430
}
private boolean catalogDropTable(Identifier ident) {
if (isPathIdentifier(ident)) {
return tables.dropTable(((PathIdentifier) ident).location(), false /* don't purge data */);
} else {
return icebergCatalog.dropTable(buildIdentifier(ident), false /* don't purge data */);
}
}
@Override
public void renameTable(Identifier from, Identifier to)
throws NoSuchTableException, TableAlreadyExistsException {
try {
checkNotPathIdentifier(from, "renameTable");
checkNotPathIdentifier(to, "renameTable");
icebergCatalog.renameTable(buildIdentifier(from), buildIdentifier(to));
} catch (org.apache.iceberg.exceptions.NoSuchTableException e) {
throw new NoSuchTableException(from);
} catch (AlreadyExistsException e) {
throw new TableAlreadyExistsException(to);
}
}
@Override
public void invalidateTable(Identifier ident) {
if (!isPathIdentifier(ident)) {
icebergCatalog.invalidateTable(buildIdentifier(ident));
}
}
@Override
public Identifier[] listTables(String[] namespace) {
return icebergCatalog.listTables(Namespace.of(namespace)).stream()
.map(ident -> Identifier.of(ident.namespace().levels(), ident.name()))
.toArray(Identifier[]::new);
}View on GitHub (pinned to 86d9c8fc54)