apache/iceberg · error · UnsupportedOperationException
Operation newTransaction is not supported after the table…
Error message
Operation newTransaction is not supported after the table is serialized
What it means
SerializableTable is an immutable, read-only snapshot of table state sent to other cluster nodes; it cannot support transactions, since a Transaction requires committing metadata updates through a live TableOperations. Calling newTransaction() therefore always throws this UnsupportedOperationException. Transactions must be opened on a table loaded from its catalog.
Solutions
- Reload the table via catalog.loadTable(location) on the node where the transaction should run, then call newTransaction() on that instance.
- Restructure so transactions are opened in the driver (where the catalog-backed Table lives) and only scan/read work is distributed using SerializableTable.
- Check instanceof SerializableTable (or !table operations support) before attempting transactional code and fail with an actionable message.
Example fix
// before Transaction tx = serializedTable.newTransaction(); // throws // after Table table = catalog.loadTable(tableLocation); Transaction tx = table.newTransaction();
Defensive patterns
Strategy: type-guard
Validate before calling
if (table instanceof org.apache.iceberg.SerializableTable) {
table = catalog.loadTable(table.location()); // reload before opening a transaction
} Type guard
boolean supportsTransactions(Table t) {
return !(t instanceof org.apache.iceberg.SerializableTable);
} Try / catch
try {
Transaction tx = table.newTransaction();
// ...
tx.commitTransaction();
} catch (UnsupportedOperationException e) {
throw new IllegalStateException("Open transactions on a catalog-loaded table, not a serialized one", e);
} Prevention
- Never distribute tables intended for writes; distribute only the location string and reload per node.
- Group multi-step writes in the driver via catalog.loadTable(...).newTransaction().
- When writing library code, take a Catalog parameter for write paths instead of a bare Table.
When it happens
Trigger: Calling table.newTransaction() on a Table instance that is a SerializableTable — e.g. inside a serialized task closure, a broadcast variable, or a table produced by SerializableTable.copyOf().
Common situations: Trying to group multiple writes/updates transactionally from within a Spark/Flink executor task where only the serialized table is available; custom integrations that pass tables across process boundaries and then attempt writes.
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 manageSnapshots is not supported after the table…
- Operation newAppend is not supported after the table is…
- Operation newDelete is not supported after the table is…
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/3c1e6147d7f0bef2.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/SerializableTable.java:432
@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;
private final String baseTableName;
protected SerializableMetadataTable(BaseMetadataTable metadataTable) {
super(metadataTable);
this.type = metadataTable.metadataTableType();View on GitHub (pinned to 86d9c8fc54)