Hmbown/CodeWhale · error · PersistenceBacklogError
receipt missing required field(s): " + ", ".join(missing)
Error message
receipt missing required field(s): " + ", ".join(missing)
What it means
Raised in validate_receipt (scripts/check-persistence-backlog-budget.py:142-146) when any of the 29 REQUIRED_RECEIPT_FIELDS (document_kind through limitations) is absent from the receipt JSON. The checker demands a complete, closed schema so partial receipts cannot silently pass the budget gate.
Source
Thrown at scripts/check-persistence-backlog-budget.py:144
"source_dirty": bool(
run(["git", "status", "--porcelain", "--untracked-files=normal"])
),
"rustc_version": run(["rustc", "--version"]),
"cargo_version": run(["cargo", "--version"]),
"build_profile": "test",
"sample_count": 1,
}
def validate_receipt(
receipt: dict[str, Any],
*,
expected_source: dict[str, Any] | None = None,
require_clean_source: bool = False,
) -> None:
missing = [field for field in REQUIRED_RECEIPT_FIELDS if field not in receipt]
if missing:
raise PersistenceBacklogError(
"receipt missing required field(s): " + ", ".join(missing)
)
if receipt["document_kind"] != RECEIPT_KIND:
raise PersistenceBacklogError(f"receipt document_kind must be {RECEIPT_KIND}")
if receipt["schema_version"] != SCHEMA_VERSION:
raise PersistenceBacklogError("receipt schema_version changed")
for field, expected in FIXTURE.items():
validate_frozen_field(field, receipt[field], expected)
if not isinstance(receipt["source_sha"], str) or not SOURCE_SHA_PATTERN.fullmatch(
receipt["source_sha"]
):
raise PersistenceBacklogError("receipt source_sha must be an exact lowercase Git SHA")
if type(receipt["source_dirty"]) is not bool:
raise PersistenceBacklogError("receipt source_dirty must be boolean")
for field, prefix in (("rustc_version", "rustc "), ("cargo_version", "cargo ")):
if not isinstance(receipt[field], str) or not receipt[field].startswith(prefix):
raise PersistenceBacklogError(f"receipt {field} must be a version string")
validate_frozen_field("build_profile", receipt["build_profile"], "test")View on GitHub (pinned to 8880682c63)
Solutions
- Regenerate the receipt via scripts/measure-persistence-backlog.py so all current fields are emitted.
- If you added a receipt field, also add it to the Rust test's receipt writer and to REQUIRED_RECEIPT_FIELDS in the same commit.
- Delete stale receipt artifacts from CI caches so the fresh emitter output is always used.
Example fix
// receipt (before, older schema)
{ "document_kind": "...", "schema_version": 2 }
// receipt (after, complete)
{ "document_kind": "...", "schema_version": 2, /* ...all 29 required keys... */ "limitations": ["..."] } Defensive patterns
Strategy: type-guard
Validate before calling
missing = [f for f in REQUIRED_RECEIPT_FIELDS if f not in receipt]
if missing:
raise SystemExit(f"incomplete receipt, regenerate: missing {', '.join(missing)}") Type guard
def has_all_required_fields(receipt: dict) -> bool:
return all(field in receipt for field in REQUIRED_RECEIPT_FIELDS) Try / catch
try:
validate_receipt(receipt)
except PersistenceBacklogError as e:
if str(e).startswith("receipt missing required field"):
# schema drift: regenerate instead of patching fields in
subprocess.run([sys.executable, "scripts/measure-persistence-backlog.py"], check=True)
raise Prevention
- Extend REQUIRED_RECEIPT_FIELDS and the Rust emitter in the same commit as any new field.
- Purge cached receipt artifacts from CI between schema bumps.
- Always generate receipts with the measure script rather than composing JSON by hand.
When it happens
Trigger: Checking a receipt written by an older schema (missing newer fields like rss_*); a truncated or hand-built JSON; the Rust test failing to populate a field; a typo'd key in the emitter (e.g. "final_version_applied" vs "finalVersionApplied").
Common situations: Schema evolution where a field was added to REQUIRED_RECEIPT_FIELDS but old receipts linger; reusing a CI-cached receipt artifact; manual receipt construction for testing.
Related errors
- {source} document_kind must be `{expected_kind}`, got {actua
- {kind} is missing required field `{dotted}`
- GitHub Release ${tag} did not provide an asset inventory
- Codewhale terminal receipt exceeded its total bound
- Codewhale stream-json line {line_number} was not an object
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/ef4d566820d06471.
Report an issue: GitHub.