apache/iceberg · error · CommitFailedException

Requirement failed: default sort order changed: expected id

Error message

Requirement failed: default sort order changed: expected id %s != %s

What it means

Thrown by AssertDefaultSortOrderId.validate when the requirement's sortOrderId differs from base.defaultSortOrderId(). The requirement asserts that the table's default sort order is still the one planned against. A mismatch means a concurrent writer replaced the default sort order (sort-order evolution), so the commit is rejected.

Source

Thrown at core/src/main/java/org/apache/iceberg/UpdateRequirement.java:227

      }
    }
  }

  class AssertDefaultSortOrderID implements UpdateRequirement {
    private final int sortOrderId;

    public AssertDefaultSortOrderID(int sortOrderId) {
      this.sortOrderId = sortOrderId;
    }

    public int sortOrderId() {
      return sortOrderId;
    }

    @Override
    public void validate(TableMetadata base) {
      if (sortOrderId != base.defaultSortOrderId()) {
        throw new CommitFailedException(
            "Requirement failed: default sort order changed: expected id %s != %s",
            sortOrderId, base.defaultSortOrderId());
      }
    }
  }
}

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Refresh the table metadata, rebuild requirements from the current defaultSortOrderId, and retry.
  2. Verify whether the operation is still valid under the new sort order and re-plan if writes depended on the old ordering.
  3. Coordinate sort-order changes with a single maintenance job/owner to prevent concurrent switches.
  4. Catch CommitFailedException and retry with backoff — the standard Iceberg optimistic-concurrency recovery.

Example fix

// before
UpdateRequirement req = new UpdateRequirement.AssertDefaultSortOrderId(1); // changed to 2
// after
table.refresh();
UpdateRequirement req = new UpdateRequirement.AssertDefaultSortOrderId(
    table.sortOrder().orderId());
Defensive patterns

Strategy: retry

Validate before calling

table.refresh();
if (table.sortOrder().orderId() != expectedSortOrderId) {
  throw new IllegalStateException("Default sort order changed; re-plan");
}

Try / catch

try {
  commitWithRequirements(reqs);
} catch (CommitFailedException e) {
  if (e.getMessage().contains("default sort order changed")) {
    table.refresh();
    reqs = rebuildRequirements(table);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Committing updates with AssertDefaultSortOrderId when base.defaultSortOrderId() != sortOrderId — another writer ran UpdateSortOrder / replaced the default sort order concurrently between planning and commit validation.

Common situations: A sort-order optimization job racing with other metadata updates; two admin jobs both changing sort order; stale client metadata in REST catalog commits; automated table-maintenance pipelines colliding with ad-hoc admin 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/0e717177c45cafdf. Report an issue: GitHub.