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
- Refresh the table metadata, rebuild requirements from the current defaultSortOrderId, and retry.
- Verify whether the operation is still valid under the new sort order and re-plan if writes depended on the old ordering.
- Coordinate sort-order changes with a single maintenance job/owner to prevent concurrent switches.
- 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
- Refresh metadata before sort-order-dependent commits
- Run sort-order changes in a single maintenance pipeline
- Do not assume a fixed sort order across job runs; read it each time
- Retry metadata commits with backoff on CommitFailedException
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
- Requirement failed: %s %s was created concurrently
- Requirement failed: %s %s has changed: expected id %s != %s
- Requirement failed: branch or tag %s is missing, expected %s
- Requirement failed: last assigned field id changed: expected
- Requirement failed: current schema changed: expected id %s !
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/0e717177c45cafdf.
Report an issue: GitHub.