apache/iceberg · error · UnsupportedOperationException
Operation manageSnapshots is not supported after the table…
Error message
Operation manageSnapshots is not supported after the table is serialized
What it means
SerializableTable is a read-only serializable copy of a table for distribution across cluster nodes; it cannot commit changes. manageSnapshots() (cherrypick/rollback of snapshots) is a mutating operation, so the implementation always throws this UnsupportedOperationException. Snapshot management must be performed on a table loaded directly from its catalog.
Solutions
- Reload the table from its catalog (catalog.loadTable(location)) on the node that performs the snapshot operation, then call manageSnapshots().
- Perform the operation in the driver where the original catalog-backed Table is available, and only ship SerializableTable for read/scan work.
- Add an instanceof check before invoking snapshot-management APIs and fail fast with a clear message or route to a catalog-loaded table.
Example fix
// before table.manageSnapshots().rollbackTo(snapshotId); // table is SerializableTable // after Table fresh = catalog.loadTable(tableLocation); fresh.manageSnapshots().rollbackTo(snapshotId);
Defensive patterns
Strategy: type-guard
Validate before calling
if (table instanceof org.apache.iceberg.SerializableTable) {
table = catalog.loadTable(table.location()); // reload before managing snapshots
} Type guard
boolean supportsSnapshotManagement(Table t) {
return !(t instanceof org.apache.iceberg.SerializableTable);
} Try / catch
try {
table.manageSnapshots().rollbackTo(snapshotId);
} catch (UnsupportedOperationException e) {
catalog.loadTable(table.location()).manageSnapshots().rollbackTo(snapshotId);
} Prevention
- Perform rollback/cherrypick in the driver where the table came from a Catalog.
- Treat any Table that crossed a serialization boundary as read-only.
- Prefer engine action APIs (e.g. Spark rollback procedures) over raw Table APIs on distributed references.
When it happens
Trigger: Calling table.manageSnapshots() (e.g. rollback, cherrypick, createBranch) on a Table that is a SerializableTable — after Java serialization to an executor or via SerializableTable.copyOf().
Common situations: Executing rollback/cherrypick logic in a distributed task where the table arrived serialized inside the closure; using a deserialized table in custom engine integrations; mistakenly treating a broadcast table as a normal catalog table.
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 expireSnapshots is not supported after the table…
- Operation newAppend is not supported after the table is…
- Operation newDelete is not supported after the table is…
- Operation newOverwrite is not supported after the table is…
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/f38108f596c00267.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/SerializableTable.java:427
@Override
public UpdateStatistics updateStatistics() {
throw new UnsupportedOperationException(errorMsg("updateStatistics"));
}
@Override
public UpdatePartitionStatistics updatePartitionStatistics() {
throw new UnsupportedOperationException(errorMsg("updatePartitionStatistics"));
}
@Override
public ExpireSnapshots expireSnapshots() {
throw new UnsupportedOperationException(errorMsg("expireSnapshots"));
}
@Override
public ManageSnapshots manageSnapshots() {
throw new UnsupportedOperationException(errorMsg("manageSnapshots"));
}
@Override
public Transaction newTransaction() {
throw new UnsupportedOperationException(errorMsg("newTransaction"));
}
@Override
public StaticTableOperations operations() {
return (StaticTableOperations) ((BaseTable) lazyTable()).operations();
}
private String errorMsg(String operation) {
return String.format("Operation %s is not supported after the table is serialized", operation);
}
public static class SerializableMetadataTable extends SerializableTable {
private final MetadataTableType type;View on GitHub (pinned to 86d9c8fc54)