apache/iceberg · error · UnsupportedOperationException
Operation updateLocation is not supported after the table is
Error message
Operation updateLocation is not supported after the table is serialized
What it means
SerializableTable is a read-only snapshot of a Table used for distributed execution (it serializes the table metadata and FileIO, but cannot commit changes back to a catalog). All mutation-producing methods like updateLocation() are overridden to throw UnsupportedOperationException with this message, because a serialized table has no live catalog connection to commit metadata updates through. If you need to mutate the table, use the original Table reference obtained from a catalog.
Source
Thrown at core/src/main/java/org/apache/iceberg/SerializableTable.java:372
@Override
public UpdatePartitionSpec updateSpec() {
throw new UnsupportedOperationException(errorMsg("updateSpec"));
}
@Override
public UpdateProperties updateProperties() {
throw new UnsupportedOperationException(errorMsg("updateProperties"));
}
@Override
public ReplaceSortOrder replaceSortOrder() {
throw new UnsupportedOperationException(errorMsg("replaceSortOrder"));
}
@Override
public UpdateLocation updateLocation() {
throw new UnsupportedOperationException(errorMsg("updateLocation"));
}
@Override
public AppendFiles newAppend() {
throw new UnsupportedOperationException(errorMsg("newAppend"));
}
@Override
public RewriteFiles newRewrite() {
throw new UnsupportedOperationException(errorMsg("newRewrite"));
}
@Override
public RewriteManifests rewriteManifests() {
throw new UnsupportedOperationException(errorMsg("rewriteManifests"));
}
@OverrideView on GitHub (pinned to 86d9c8fc54)
Solutions
- Use the original Table reference from the catalog (Catalog.loadTable) instead of the SerializableTable copy when calling updateLocation()
- Check whether the code path is running on a driver/catalog-connected node rather than on a distributed worker holding a serialized table
- Restructure so mutation operations run outside the serialized-table scope: collect results on workers, then apply updates via the catalog-backed Table on the driver
- If the framework hands you a Table, verify it is not a SerializableTable (instanceof SerializableTable) before attempting writes
Example fix
// before Table table = SerializableTable.wrap(driverTable); table.updateLocation().setLocation(newLoc).commit(); // after Table table = catalog.loadTable(identifier); // live, catalog-backed table table.updateLocation().setLocation(newLoc).commit();
Defensive patterns
Strategy: try-catch
Validate before calling
if (table instanceof org.apache.iceberg.SerializableTable) {
throw new IllegalStateException("Use a catalog-backed Table, not a SerializableTable, for commits");
} Type guard
function isSerializableTable(t) { return t instanceof org.apache.iceberg.SerializableTable; } // guard in Java: boolean ok = !(table instanceof SerializableTable); Try / catch
try {
table.updateLocation().setLocation(loc).commit();
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("not supported after the table is serialized")) {
table = catalog.loadTable(identifier); // re-load live table and retry
table.updateLocation().setLocation(loc).commit();
} else { throw e; }
} Prevention
- Keep SerializableTable instances strictly for read/scan work on workers
- Always reload the table from the Catalog before any commit-producing operation
- In shared helper APIs, document/require a catalog-backed Table and fail fast on SerializableTable
- Remember serialization severs the catalog connection: only reads survive
When it happens
Trigger: Calling table.updateLocation() on a table instance that was wrapped by SerializableTable and deserialized after shipping across a task boundary (e.g. inside a Spark/Flink executor task).
Common situations: Framework-internal misuse where a serialized table is accidentally used as if it were the driver-side table; custom sink/committer code storing a SerializableTable and later attempting to set the table location; accidentally serializing a Table with SerializableTable.wrap(table) then reusing the wrapped copy for 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
- 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
- Operation newOverwrite is not supported after the table is s
- Operation newRowDelta is not supported after the table is se
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/81cd55001b0500d4.
Report an issue: GitHub.