{"record":{"id":"71f2cbcf96580d7b","repo":"Hmbown/CodeWhale","slug":"receipt-schema-version-changed","errorCode":null,"errorMessage":"receipt schema_version changed","messagePattern":"receipt schema_version changed","errorType":"validation","errorClass":"PersistenceBacklogError","httpStatus":null,"severity":"error","filePath":"scripts/check-persistence-backlog-budget.py","lineNumber":150,"sourceCode":"        \"sample_count\": 1,\n    }\n\n\ndef validate_receipt(\n    receipt: dict[str, Any],\n    *,\n    expected_source: dict[str, Any] | None = None,\n    require_clean_source: bool = False,\n) -> None:\n    missing = [field for field in REQUIRED_RECEIPT_FIELDS if field not in receipt]\n    if missing:\n        raise PersistenceBacklogError(\n            \"receipt missing required field(s): \" + \", \".join(missing)\n        )\n    if receipt[\"document_kind\"] != RECEIPT_KIND:\n        raise PersistenceBacklogError(f\"receipt document_kind must be {RECEIPT_KIND}\")\n    if receipt[\"schema_version\"] != SCHEMA_VERSION:\n        raise PersistenceBacklogError(\"receipt schema_version changed\")\n    for field, expected in FIXTURE.items():\n        validate_frozen_field(field, receipt[field], expected)\n    if not isinstance(receipt[\"source_sha\"], str) or not SOURCE_SHA_PATTERN.fullmatch(\n        receipt[\"source_sha\"]\n    ):\n        raise PersistenceBacklogError(\"receipt source_sha must be an exact lowercase Git SHA\")\n    if type(receipt[\"source_dirty\"]) is not bool:\n        raise PersistenceBacklogError(\"receipt source_dirty must be boolean\")\n    for field, prefix in ((\"rustc_version\", \"rustc \"), (\"cargo_version\", \"cargo \")):\n        if not isinstance(receipt[field], str) or not receipt[field].startswith(prefix):\n            raise PersistenceBacklogError(f\"receipt {field} must be a version string\")\n    validate_frozen_field(\"build_profile\", receipt[\"build_profile\"], \"test\")\n    validate_frozen_field(\"sample_count\", receipt[\"sample_count\"], 1)\n    if expected_source is not None:\n        for field in (\n            \"source_sha\",\n            \"source_dirty\",\n            \"rustc_version\",","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/scripts/check-persistence-backlog-budget.py#L132-L168","documentation":"The receipt's `schema_version` must equal the constant `SCHEMA_VERSION = 2` defined in scripts/check-persistence-backlog-budget.py:23. If a receipt was produced by an older (version 1) or newer producer whose schema layout no longer matches what this validator expects, the check refuses to interpret the fields. This guards against silently validating a document whose semantics changed between releases.","triggerScenarios":"Validating a receipt JSON with `schema_version` of 1, 3, or a string like \"2\"; the measurement script and the checking script were updated out of sync in different branches.","commonSituations":"Reusing a committed receipt from before a schema bump; merging an old branch's receipt with the new checker; hand-written receipts copied from old documentation.","solutions":["Regenerate the receipt with the current scripts/measure-persistence-backlog.py so schema_version is 2","Set `schema_version` to the integer 2 in the receipt (note: it must be the number 2, not the string \"2\")","Update the checker and measurement scripts together from the same commit so their schema versions match"],"exampleFix":"// before\n{\"schema_version\": \"2\", ...}\n// after\n{\"schema_version\": 2, ...}","handlingStrategy":"validation","validationCode":"assert receipt.get(\"schema_version\") == 2, receipt.get(\"schema_version\")","typeGuard":"def is_current_schema(doc):\n    return isinstance(doc, dict) and doc.get(\"schema_version\") is 2 if isinstance(doc, dict) and type(doc.get(\"schema_version\")) is int else False","tryCatchPattern":"try:\n    validate_receipt(receipt)\nexcept PersistenceBacklogError as e:\n    if \"schema_version changed\" in str(e):\n        receipt = regenerate_receipt()  # re-measure with current scripts","preventionTips":["Regenerate receipts after any schema bump; never reuse old committed receipts","Pin checker and measurement scripts to the same commit in CI","Use the integer 2, never the string \"2\""],"tags":["schema","versioning","validation","receipt"],"backgroundTag":"schema-validation-failed","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}