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
- Resolve the actual current Table from the catalog (catalog.loadTable(identifier)) instead of using the read-only/snapshot wrapper.
- Guard generic write code with a capability check before calling newReplacePartitions().
- 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
- Only call write APIs on tables loaded from catalog.loadTable(identifier)
- Use snapshot handles solely for time-travel reads
- Centralize write paths in a utility that resolves a writable table handle first
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
- Cannot add partition field to non-Iceberg table: $table
- Cannot append to a table
- Cannot apply unknown modify-column change:
- Cannot apply unknown modify-column-position change:
- Cannot apply unknown unique constraint:
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)