apache/iceberg · error · java.lang.UnsupportedOperationException
SparkCachedTableCatalog does not support altering tables
Error message
SparkCachedTableCatalog does not support altering tables
What it means
SparkCachedTableCatalog is a read-only catalog that serves Iceberg tables from an in-process cache (e.g. for cached table scans in Spark). It intentionally implements the Spark CatalogPlugin DDL surface but rejects every mutation. alterTable() throws UnsupportedOperationException because cached tables are snapshots of existing tables and must be altered through the real catalog that owns them.
Source
Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/SparkCachedTableCatalog.java:103
long snapshotId = SnapshotUtil.snapshotIdAsOfTime(table.table(), timestampMillis);
return table.copyWithSnapshotId(snapshotId);
}
@Override
public void invalidateTable(Identifier ident) {
throw new UnsupportedOperationException(CLASS_NAME + " does not support table invalidation");
}
@Override
public SparkTable createTable(
Identifier ident, StructType schema, Transform[] partitions, Map<String, String> properties)
throws TableAlreadyExistsException {
throw new UnsupportedOperationException(CLASS_NAME + " does not support creating tables");
}
@Override
public SparkTable alterTable(Identifier ident, TableChange... changes) {
throw new UnsupportedOperationException(CLASS_NAME + " does not support altering tables");
}
@Override
public boolean dropTable(Identifier ident) {
throw new UnsupportedOperationException(CLASS_NAME + " does not support dropping tables");
}
@Override
public boolean purgeTable(Identifier ident) throws UnsupportedOperationException {
throw new UnsupportedOperationException(CLASS_NAME + " does not support purging tables");
}
@Override
public void renameTable(Identifier oldIdent, Identifier newIdent) {
throw new UnsupportedOperationException(CLASS_NAME + " does not support renaming tables");
}
@OverrideView on GitHub (pinned to 86d9c8fc54)
Solutions
- Resolve the table through the real catalog (SparkCatalog / HiveCatalog / HadoopCatalog) and apply the TableChange there.
- Use ALTER TABLE on the original unqualified or properly catalog-qualified identifier so Spark does not route to SparkCachedTableCatalog.
- If you own the code path, hold the underlying org.apache.iceberg.Table and use table.updateSchema()/updateProperties() instead of the catalog DDL API.
Example fix
// before
SparkCachedTableCatalog catalog = ...;
catalog.alterTable(Identifier.of(new String[]{"db"}, "t"), TableChange.addColumn("c", Types.IntegerType.get()));
// after
SparkCatalog realCatalog = ...; // catalog that actually owns the table
realCatalog.alterTable(Identifier.of(new String[]{"db"}, "t"), TableChange.addColumn("c", Types.IntegerType.get())); Defensive patterns
Strategy: validation
Validate before calling
if (catalog instanceof SparkCachedTableCatalog || catalog.name().contains("CachedTable")) {
throw new IllegalArgumentException("DDL not supported on cached table catalog; use the owning catalog");
} Type guard
boolean supportsDdl = !(catalog instanceof SparkCachedTableCatalog);
Prevention
- Treat SparkCachedTableCatalog as read-only by design; route all ALTER/DROP/PURGE/RENAME to the owning catalog.
- Use fully qualified identifiers (spark_catalog.db.t) in SQL so DDL resolves to the real catalog.
- In generic tooling, feature-detect catalog capabilities before invoking DDL methods.
When it happens
Trigger: Calling SparkCachedTableCatalog.alterTable(ident, changes...) directly, or running Spark SQL DDL (ALTER TABLE ... / DESCRIBE-driven ALTER) whose catalog resolution lands on the cached-table catalog (identifiers like 'spark_catalog.<cached-namespace>.<table>').
Common situations: Pasting an ALTER TABLE statement into a session where the table was loaded through the cached catalog; programmatically applying TableChange objects against the cache-backed catalog; framework code that generically applies schema evolution to whatever catalog the identifier resolves to.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- SparkCachedTableCatalog does not support dropping tables
- SparkCachedTableCatalog does not support purging tables
- SparkCachedTableCatalog does not support renaming tables
- does not support creating tables
- does not support altering tables
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/32083a62f69f6ec8.
Report an issue: GitHub.