apache/iceberg · error · UnsupportedOperationException

Operation updateSpec is not supported after the table is ser

Error message

Operation updateSpec is not supported after the table is serialized

What it means

SerializableTable guard: the table was serialized to a remote engine and this handle carries only read state, so updateSpec() (partition-spec evolution) is refused. Mutating operations must go through the original Table obtained from the catalog in the driver, not the deserialized copy.

Source

Thrown at core/src/main/java/org/apache/iceberg/SerializableTable.java:357

  @Override
  public Iterable<Snapshot> snapshots() {
    return lazyTable().snapshots();
  }

  @Override
  public List<HistoryEntry> history() {
    return lazyTable().history();
  }

  @Override
  public UpdateSchema updateSchema() {
    throw new UnsupportedOperationException(errorMsg("updateSchema"));
  }

  @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

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Perform the partition evolution on the driver with a live catalog table
  2. Pass a reference to the Catalog and identifier instead of the serialized table
  3. Restrict SerializableTable usage to read paths (scans, reads)
Defensive patterns

Strategy: validation

Validate before calling

if (table instanceof SerializableTable) { throw new UnsupportedOperationException("Spec updates require a live catalog table"); }

Type guard

boolean canWrite = !(table instanceof SerializableTable);

Try / catch

try { table.updateSpec().commit(); } catch (UnsupportedOperationException e) { catalog.loadTable(id).updateSpec().commit(); }

Prevention

When it happens

Trigger: Calling updateSpec() on a SerializableTable instance, e.g., in distributed task code or after wrapping with SerializableTable.of().

Common situations: Job code that evolves partitioning mid-pipeline using a table handle that was serialized for executors.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/48ed2e6203c29c3a. Report an issue: GitHub.