{"record":{"id":"8f3f4cd281c8bbd8","repo":"apache/iceberg","slug":"requirement-failed-last-assigned-partition-id-cha","errorCode":null,"errorMessage":"Requirement failed: last assigned partition id changed: expected id %s != %s","messagePattern":"Requirement failed: last assigned partition id changed: expected id (.+?) != (.+?)","errorType":"exception","errorClass":"CommitFailedException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/UpdateRequirement.java","lineNumber":185,"sourceCode":"      }\n    }\n  }\n\n  class AssertLastAssignedPartitionId implements UpdateRequirement {\n    private final int lastAssignedPartitionId;\n\n    public AssertLastAssignedPartitionId(int lastAssignedPartitionId) {\n      this.lastAssignedPartitionId = lastAssignedPartitionId;\n    }\n\n    public int lastAssignedPartitionId() {\n      return lastAssignedPartitionId;\n    }\n\n    @Override\n    public void validate(TableMetadata base) {\n      if (base != null && base.lastAssignedPartitionId() != lastAssignedPartitionId) {\n        throw new CommitFailedException(\n            \"Requirement failed: last assigned partition id changed: expected id %s != %s\",\n            lastAssignedPartitionId, base.lastAssignedPartitionId());\n      }\n    }\n  }\n\n  class AssertDefaultSpecID implements UpdateRequirement {\n    private final int specId;\n\n    public AssertDefaultSpecID(int specId) {\n      this.specId = specId;\n    }\n\n    public int specId() {\n      return specId;\n    }\n\n    @Override","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/UpdateRequirement.java#L167-L203","documentation":"Thrown by AssertLastAssignedPartitionId.validate when the requirement's lastAssignedPartitionId does not match base.lastAssignedPartitionId() (the highest partition field ID assigned in any spec). Partition field IDs are also monotonic and must never be reused; the assertion detects concurrent partition-spec evolution (AddPartitionField/RemovePartitionField) between planning and commit.","triggerScenarios":"Committing updates (e.g. ReplacePartitionSpec or UpdatePartitionSpec flows) whose requirements include AssertLastAssignedPartitionId when base.lastAssignedPartitionId() differs — another writer added or removed partition fields concurrently.","commonSituations":"Two jobs repartition the table at once; a partition-evolution migration racing with routine partition-field additions; REST catalog commits built from a stale table version where another client already extended the spec.","solutions":["Refresh the table metadata, rebuild requirements with the current lastAssignedPartitionId, and retry.","Re-apply the partition-spec change against the refreshed spec so new partition field IDs are assigned from the current max.","Coordinate partition evolution through a single migration job/owner to avoid racing writers.","Catch CommitFailedException and retry with backoff; this is the intended recovery path for concurrent-commit conflicts."],"exampleFix":"// before\nUpdateRequirement req = new UpdateRequirement.AssertLastAssignedPartitionId(7); // now 9\n// after\ntable.refresh();\nUpdateRequirement req = new UpdateRequirement.AssertLastAssignedPartitionId(\n    table.spec().lastAssignedPartitionId());","handlingStrategy":"retry","validationCode":"table.refresh();\nif (table.spec().lastAssignedPartitionId() != assertedPartitionId) {\n  throw new IllegalStateException(\"Partition spec evolved; re-plan\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  commitPartitionEvolution();\n} catch (CommitFailedException e) {\n  if (e.getMessage().contains(\"last assigned partition id changed\")) {\n    table.refresh();\n    reapplySpecChange(table);\n  } else { throw e; }\n}","preventionTips":["Serialize partition-evolution changes through a single job","Refresh metadata before spec-related commits","Derive partition field IDs from the current spec, never constants","Retry with backoff on CommitFailedException"],"tags":["concurrency","partition-spec","commit-failed","iceberg"],"backgroundTag":"invalid-state-transition","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}