apache/iceberg · error · UnsupportedOperationException
Cannot call commit on temporary table operations
Error message
Cannot call commit on temporary table operations
What it means
TemporaryTableOperations cannot persist anything: it wraps uncommitted metadata with no metastore backing. Its commit() override throws UnsupportedOperationException so callers cannot mistakenly treat staged/uncommitted metadata as a durable commit. Use the owning catalog or real TableOperations to persist changes.
Source
Thrown at core/src/main/java/org/apache/iceberg/BaseMetastoreTableOperations.java:254
}
@Override
public TableOperations temp(TableMetadata uncommittedMetadata) {
return new TableOperations() {
@Override
public TableMetadata current() {
return uncommittedMetadata;
}
@Override
public TableMetadata refresh() {
throw new UnsupportedOperationException(
"Cannot call refresh on temporary table operations");
}
@Override
public void commit(TableMetadata base, TableMetadata metadata) {
throw new UnsupportedOperationException("Cannot call commit on temporary table operations");
}
@Override
public String metadataFileLocation(String fileName) {
return BaseMetastoreTableOperations.this.metadataFileLocation(
uncommittedMetadata, fileName);
}
@Override
public LocationProvider locationProvider() {
return LocationProviders.locationsFor(
uncommittedMetadata.location(), uncommittedMetadata.properties());
}
@Override
public FileIO io() {
return BaseMetastoreTableOperations.this.io();
}View on GitHub (pinned to 86d9c8fc54)
Solutions
- Complete the staged transaction through the catalog API (e.g., commit the transaction or create from staged metadata) rather than calling commit on temporary ops
- Use catalog.buildTable(...).createTransaction()/createOrReplaceTransaction() and commit the Transaction object
- Route persistence through a metastore-backed TableOperations instance
Example fix
// before tempOps.commit(base, metadata); // UnsupportedOperationException // after Transaction tx = catalog.buildTable(ident, schema).createTransaction(); // ... apply changes via tx ... tx.commitTransaction(); // persists through the real catalog
Defensive patterns
Strategy: type-guard
Validate before calling
if (isTemporaryOps(ops)) { throw new IllegalStateException("Use the catalog/Transaction to persist changes"); } else { ops.commit(base, metadata); } Type guard
boolean isTemporaryOps(TableOperations ops) { return ops instanceof BaseMetastoreTableOperations && !supportsRealCommit; /* flag set when temporary ops are created */ } Try / catch
try { ops.commit(base, metadata); }
catch (UnsupportedOperationException e) { /* temporary ops: persist via Transaction.commitTransaction() instead */ } Prevention
- Never persist through temporary operations handles
- Always use Transaction APIs for staged changes
- Keep staged (dry-run) and committed flows in separate code paths
When it happens
Trigger: Calling commit(base, metadata) on temporary operations from transaction staging (e.g., staged create/replace flows); trying to 'save' staged metadata directly instead of completing the transaction.
Common situations: Misunderstanding staged transaction APIs and attempting to commit via the temporary ops handle; utility code shared between normal and staged flows; attempting to persist an uncommitted metadata tree during a dry-run.
Related errors
- Cannot call refresh on temporary table operations
- Cannot call refresh on temporary table operations
- Cannot call commit on temporary table operations
- Update type %s is not supported
- Cannot call commit on temporary table operations
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/f134daf88e587b2a.
Report an issue: GitHub.