apache/iceberg · error · UnsupportedOperationException

Cannot replace partitions in a

Error message

Cannot replace partitions in a %s table

What it means

BaseReadOnlyTable wraps a table snapshot in a read-only view (e.g. a time-travel snapshot reference or metadata table). All mutation APIs are disabled, so calling newReplacePartitions() throws UnsupportedOperationException. The library cannot accept row replacements against a table that has no write path to the current table metadata.

Solutions

  1. Resolve the actual current Table from the catalog (catalog.loadTable(identifier)) instead of using the read-only/snapshot wrapper.
  2. Guard generic write code with a capability check before calling newReplacePartitions().
  3. If the intent is snapshot-based writes, create a branching/writing through WAP or branch references on the real table.

Example fix

// before
Table snapshotView = getReadOnlyTable();
snapshotView.newReplacePartitions().appendFile(dataFile).commit();
// after
Table table = catalog.loadTable(tableIdentifier);
table.newReplacePartitions().appendFile(dataFile).commit();
Defensive patterns

Strategy: validation

Validate before calling

// Java
if (table instanceof BaseReadOnlyTable || isReadOnly(table)) {
  throw new IllegalStateException("Table handle is read-only; load via catalog.loadTable() to write");
}
table.newReplacePartitions()...

Type guard

boolean isWritable(Table t) { return !(t instanceof BaseReadOnlyTable); }

Try / catch

try { table.newReplacePartitions()...commit(); } catch (UnsupportedOperationException e) { /* fall back to catalog.loadTable() */ }

Prevention

When it happens

Trigger: Calling table.newReplacePartitions() on a Table instance backed by BaseReadOnlyTable — i.e. a snapshot object or other read-only descriptor obtained from Iceberg metadata rather than a writable table handle.

Common situations: Fetching a snapshot via table.snapshot(...)-style read-only wrappers, using a metadata/view table as if it were a base table, or passing a read-only table handle into generic code that performs overwrite-by-partition 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


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

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/BaseReadOnlyTable.java:88

  public RewriteManifests rewriteManifests() {
    throw new UnsupportedOperationException(
        "Cannot rewrite manifests in a " + descriptor + " table");
  }

  @Override
  public OverwriteFiles newOverwrite() {
    throw new UnsupportedOperationException("Cannot overwrite in a " + descriptor + " table");
  }

  @Override
  public RowDelta newRowDelta() {
    throw new UnsupportedOperationException(
        "Cannot remove or replace rows in a " + descriptor + " table");
  }

  @Override
  public ReplacePartitions newReplacePartitions() {
    throw new UnsupportedOperationException(
        "Cannot replace partitions in a " + descriptor + " table");
  }

  @Override
  public DeleteFiles newDelete() {
    throw new UnsupportedOperationException("Cannot delete from a " + descriptor + " table");
  }

  @Override
  public UpdateStatistics updateStatistics() {
    throw new UnsupportedOperationException(
        "Cannot update statistics of a " + descriptor + " table");
  }

  @Override
  public UpdatePartitionStatistics updatePartitionStatistics() {
    throw new UnsupportedOperationException(
        "Cannot update partition statistics of a " + descriptor + " table");

View on GitHub (pinned to 86d9c8fc54)