apache/iceberg · error · UnsupportedOperationException
${this.getClass().getName()} does not support operations()
Error message
${this.getClass().getName()} does not support operations() What it means
SerializableMetadataTable is the serializable wrapper for Iceberg metadata tables (e.g. table.files, table.history, table.refs). Unlike the plain SerializableTable, whose operations() lazily wraps a StaticTableOperations, metadata tables are instantiated through MetadataTableUtils and expose no StaticTableOperations, so operations() is intentionally unimplemented and always throws UnsupportedOperationException.
Source
Thrown at core/src/main/java/org/apache/iceberg/SerializableTable.java:461
public static class SerializableMetadataTable extends SerializableTable {
private final MetadataTableType type;
private final String baseTableName;
protected SerializableMetadataTable(BaseMetadataTable metadataTable) {
super(metadataTable);
this.type = metadataTable.metadataTableType();
this.baseTableName = metadataTable.table().name();
}
@Override
protected Table newTable(TableOperations ops, String tableName) {
return MetadataTableUtils.createMetadataTableInstance(ops, baseTableName, tableName, type);
}
@Override
public StaticTableOperations operations() {
throw new UnsupportedOperationException(
this.getClass().getName() + " does not support operations()");
}
public MetadataTableType type() {
return type;
}
}
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Do not call operations() on metadata tables; instead use the metadata-table-specific APIs (e.g. scan via newScan(), MetadataTableType via type()).
- If the underlying base table's operations are needed, keep a reference to the original BaseMetadataTable (or reload it from the catalog) and call operations() on the base table, not the serialized wrapper.
- Recreate the metadata table on demand with MetadataTableUtils.createMetadataTableInstance(ops, baseTableName, tableName, type) instead of deserializing it.
Example fix
// before TableOperations ops = ((HasTableOperations) serializedMetadataTable).operations(); // throws // after Table base = catalog.loadTable(baseTableLocation); MetadataTableUtils.createMetadataTableInstance(base.operations(), baseTableName, name, type);
Defensive patterns
Strategy: type-guard
Validate before calling
if (table instanceof org.apache.iceberg.SerializableTable.SerializableMetadataTable) {
// operations() is unsupported; use newScan()/type() or recreate via MetadataTableUtils
} Type guard
boolean supportsOperationsAccess(Table t) {
return t instanceof org.apache.iceberg.HasTableOperations
&& !(t instanceof org.apache.iceberg.SerializableTable.SerializableMetadataTable);
} Try / catch
try {
TableOperations ops = ((HasTableOperations) table).operations();
// ...
} catch (UnsupportedOperationException e) {
// recreate the metadata table from the base table's operations
Table base = catalog.loadTable(baseTableLocation);
Table meta = MetadataTableUtils.createMetadataTableInstance(
((HasTableOperations) base).operations(), baseTableName, tableName, type);
} Prevention
- Access metadata tables through scan APIs (newScan) rather than TableOperations.
- Keep metadata-table wrappers from crossing serialization boundaries; recreate them from the base table.
- When operations() is genuinely required, hold a reference to the original BaseMetadataTable or reload it from the catalog.
When it happens
Trigger: Calling operations() on a serialized metadata table (SerializableMetadataTable), typically obtained when a metadata table instance was passed through serialization (broadcast/closure) or cast to a type exposing operations(); code paths that require HasTableOperations on metadata tables also hit this.
Common situations: Engine integration or utility code that inspects TableOperations of a metadata table after distribution; Kryo/Java deserialization of metadata tables (e.g. files/meta tables) in Spark executors followed by API calls needing operations().
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
- Cannot serialize type: + typeId
- Operation updateLocation is not supported after the table is
- Operation newAppend is not supported after the table is seri
- Operation newRewrite is not supported after the table is ser
- Operation rewriteManifests is not supported after the table
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/f007a024feb9c104.
Report an issue: GitHub.