{"record":{"id":"918141c9f12afdca","repo":"Hmbown/CodeWhale","slug":"receipt-field-must-remain-expected-r-got-val","errorCode":null,"errorMessage":"receipt {field} must remain {expected!r}, got {value!r}","messagePattern":"receipt (.+?) must remain (.+?), got (.+?)","errorType":"exception","errorClass":"PersistenceBacklogError","httpStatus":null,"severity":"error","filePath":"scripts/check-persistence-backlog-budget.py","lineNumber":104,"sourceCode":"def load_json(path: Path, label: str) -> dict[str, Any]:\n    try:\n        value = json.loads(path.read_text(encoding=\"utf-8\"))\n    except (OSError, json.JSONDecodeError) as error:\n        raise PersistenceBacklogError(f\"invalid {label} {path}: {error}\") from error\n    if not isinstance(value, dict):\n        raise PersistenceBacklogError(f\"{label} must be a JSON object\")\n    return value\n\n\ndef non_negative_integer(value: Any, field: str) -> int:\n    if isinstance(value, bool) or not isinstance(value, int) or value < 0:\n        raise PersistenceBacklogError(f\"{field} must be a non-negative integer\")\n    return value\n\n\ndef validate_frozen_field(field: str, value: Any, expected: Any) -> None:\n    if type(value) is not type(expected) or value != expected:\n        raise PersistenceBacklogError(\n            f\"receipt {field} must remain {expected!r}, got {value!r}\"\n        )\n\n\ndef current_source_identity() -> dict[str, Any]:\n    def run(command: list[str]) -> str:\n        result = subprocess.run(\n            command,\n            cwd=ROOT,\n            text=True,\n            capture_output=True,\n            check=False,\n        )\n        if result.returncode != 0:\n            raise PersistenceBacklogError(\n                f\"source provenance command failed: {' '.join(command)}\"\n            )\n        return result.stdout.strip()","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/scripts/check-persistence-backlog-budget.py#L86-L122","documentation":"Raised by validate_frozen_field (scripts/check-persistence-backlog-budget.py:102-106) when a receipt's frozen fixture field differs in type or value from the FIXTURE constant. The checker pins the measurement workload (fixture_id, request_variant, payload_estimator, paused_consumer, requests_attempted=128, content_bytes_per_request=65536, single_session_id, expected_applied_version=127) plus build_profile=\"test\" and sample_count=1, so any drift between the receipt and the checker's frozen contract aborts the gate.","triggerScenarios":"Checking a --receipt JSON produced by an older/newer measurement test whose workload differs; editing FIXTURE in the checker (e.g. bumping requests_attempted) without re-measuring the receipt; hand-editing the receipt JSON; a stale baseline receipt after the Rust test's fixture changed.","commonSituations":"Schema/workload evolution where the Rust test and the Python checker were updated in different commits; regenerating the budget but reusing an old receipt; cherry-picking a fixture change without the matching re-measurement.","solutions":["Re-run scripts/measure-persistence-backlog.py (or run the checker without --receipt so it measures fresh) to regenerate a receipt matching the current fixture.","If the workload change is intentional, update FIXTURE in check-persistence-backlog-budget.py, the Rust measurement test, the budget's fixture block, and the baseline receipt together in one commit.","Discard any manual edits to receipt JSON — receipts are provenance artifacts, not configuration.","Verify the receipt was produced from the same commit as the checker you are running."],"exampleFix":"// receipt (before)\n\"requests_attempted\": 64\n// receipt (after, matches FIXTURE)\n\"requests_attempted\": 128","handlingStrategy":"validation","validationCode":"import json, sys\nsys.path.insert(0, \"scripts\")\nfrom check_persistence_backlog_budget import FIXTURE  # or inline the constant\n\nreceipt = json.load(open(\"receipt.json\"))\nfor field, expected in FIXTURE.items():\n    if type(receipt.get(field)) is not type(expected) or receipt.get(field) != expected:\n        sys.exit(f\"stale receipt: fixture field {field} drifted; re-measure\")","typeGuard":"def fixture_matches(receipt: dict) -> bool:\n    return all(\n        type(receipt.get(f)) is type(exp) and receipt.get(f) == exp\n        for f, exp in FIXTURE.items()\n    )","tryCatchPattern":"try:\n    validate_receipt(receipt)\nexcept PersistenceBacklogError as e:\n    if \"must remain\" in str(e):\n        raise RuntimeError(\"receipt predates the current fixture; regenerate it\") from e\n    raise","preventionTips":["Treat receipts as single-run artifacts tied to the current FIXTURE; never cache them across workload changes.","Update FIXTURE, the Rust emitter, the budget, and the baseline receipt in one atomic commit.","Never hand-edit receipt JSON."],"tags":["validation","json","fixture","regression"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}