Hmbown/CodeWhale · error · PersistenceBacklogError
receipt document_kind must be
Error message
receipt document_kind must be {RECEIPT_KIND} What it means
`validate_receipt` requires that `document_kind` equal the exact string `codewhale.persistence_backlog_receipt`. This discriminator marks the JSON document as a persistence backlog measurement receipt and prevents a budget file or other document from being validated as a receipt. A wrong kind means the file is not the artifact this validator accepts.
Solutions
- Set `document_kind` to exactly `"codewhale.persistence_backlog_receipt"` in the receipt JSON
- Verify you did not pass the budget file via `--receipt` (the budget uses kind `codewhale.persistence_backlog_budget`)
- Regenerate the receipt with the measurement script so the kind is set correctly
Example fix
// before
{"document_kind": "codewhale.persistence_backlog_budget", ...}
// after
{"document_kind": "codewhale.persistence_backlog_receipt", ...} Defensive patterns
Strategy: validation
Validate before calling
assert receipt.get("document_kind") == "codewhale.persistence_backlog_receipt", receipt.get("document_kind") Type guard
def is_receipt(doc):
return isinstance(doc, dict) and doc.get("document_kind") == "codewhale.persistence_backlog_receipt" Try / catch
try:
validate_receipt(receipt)
except PersistenceBacklogError as e:
if "document_kind" in str(e):
check_arguments_for_swapped_receipt_and_budget() Prevention
- Double-check you pass the receipt file to --receipt and the budget to --budget
- Copy document_kind verbatim from the baseline receipt
- Never rename document_kind in receipts
When it happens
Trigger: Pointing `--receipt` at the budget JSON (`codewhale.persistence_backlog_budget`) or at the baseline receipt reference with an edited document_kind; a typo or rename of document_kind in a hand-written receipt.
Common situations: Swapping the --receipt and --budget argument values by mistake; renaming document_kind to a project-local value; generating a receipt with an out-of-tree tool that uses a different kind string.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- receipt missing required field(s)
- invalid : top level must be an object
- must be a JSON object
- receipt schema_version changed
- receipt source_dirty must be boolean
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/3e96bf6d834e0498.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/check-persistence-backlog-budget.py:148
"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")
validate_frozen_field("sample_count", receipt["sample_count"], 1)
if expected_source is not None:
for field in (
"source_sha",View on GitHub (pinned to 433685b202)