apache/iceberg · info · CommitFailedException

Table metadata refresh is required

Error message

Table metadata refresh is required

What it means

This CommitFailedException is thrown internally by the transaction's inner commit when the metadata the transaction was built on (underlyingBase) no longer matches the transaction's current metadata. It is a control-flow signal that triggers Iceberg's standard retry loop, which refreshes table metadata and re-applies updates. Callers normally never see it unless retries are exhausted.

Solutions

  1. No user action needed in the normal case — Iceberg retries and refreshes automatically
  2. If retries are exhausted, refresh the table and re-run the transaction
  3. Reduce the number of concurrent metadata writers to lower conflict frequency
  4. Upgrade Iceberg if retry exhaustion occurs frequently
Defensive patterns

Strategy: retry

Try / catch

catch (CommitFailedException e) { table.refresh(); retryCommit(); } — the library's retry loop handles this; only handle at the outermost layer

Prevention

When it happens

Trigger: Another committer changes the table metadata between transaction start and commit, so the underlying table ops' current metadata differs from the transaction's base when commit(TableMetadata, TableMetadata) runs.

Common situations: Concurrent commits from other jobs/engines (e.g. compaction running while a transaction is open); external catalog refreshes; long transactions spanning metadata changes.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/BaseTransaction.java:486

  public class TransactionTableOperations implements TableOperations {
    private TableOperations tempOps = ops.temp(current);

    @Override
    public TableMetadata current() {
      return current;
    }

    @Override
    public TableMetadata refresh() {
      return current;
    }

    @Override
    @SuppressWarnings("ConsistentOverrides")
    public void commit(TableMetadata underlyingBase, TableMetadata metadata) {
      if (underlyingBase != current) {
        // trigger a refresh and retry
        throw new CommitFailedException("Table metadata refresh is required");
      }

      BaseTransaction.this.current = metadata;

      this.tempOps = ops.temp(metadata);

      BaseTransaction.this.hasLastOpCommitted = true;
    }

    @Override
    public FileIO io() {
      return tempOps.io();
    }

    @Override
    public EncryptionManager encryption() {
      return tempOps.encryption();
    }

View on GitHub (pinned to 86d9c8fc54)