Hmbown/CodeWhale · error · PersistenceBacklogError
budget document_kind must be {BUDGET_KIND}
Error message
budget document_kind must be {BUDGET_KIND} What it means
Raised by validate_budget() when the loaded budget JSON's document_kind is not the exact discriminator 'codewhale.persistence_backlog_budget' (BUDGET_KIND). The discriminator guarantees the checker validates the intended document class and never silently accepts a receipt, a differently-versioned budget, or an unrelated JSON file passed via --budget.
Source
Thrown at scripts/check-persistence-backlog-budget.py:244
if receipt["rss_supported"]:
for field in rss_fields:
non_negative_integer(receipt[field], field)
before = receipt["rss_before_bytes"]
if receipt["rss_during_delta_bytes"] != max(
0, receipt["rss_during_bytes"] - before
):
raise PersistenceBacklogError("rss_during_delta_bytes is inconsistent")
if receipt["rss_after_delta_bytes"] != max(
0, receipt["rss_after_bytes"] - before
):
raise PersistenceBacklogError("rss_after_delta_bytes is inconsistent")
elif any(receipt[field] is not None for field in rss_fields):
raise PersistenceBacklogError("unsupported RSS fields must be null")
def validate_budget(budget: dict[str, Any]) -> None:
if budget.get("document_kind") != BUDGET_KIND:
raise PersistenceBacklogError(f"budget document_kind must be {BUDGET_KIND}")
if budget.get("schema_version") != SCHEMA_VERSION:
raise PersistenceBacklogError("budget schema_version changed")
fixture = budget.get("fixture")
if not isinstance(fixture, dict) or set(fixture) != set(FIXTURE):
raise PersistenceBacklogError("budget fixture no longer matches the frozen workload")
for field, expected in FIXTURE.items():
if type(fixture[field]) is not type(expected) or fixture[field] != expected:
raise PersistenceBacklogError(
f"budget fixture.{field} must remain {expected!r}"
)
if budget.get("baseline_receipt") != BASELINE_RECEIPT_REFERENCE:
raise PersistenceBacklogError("budget baseline_receipt path changed")
ceilings = budget.get("ceilings")
baseline = budget.get("baseline_observation")
if not isinstance(ceilings, dict) or not isinstance(baseline, dict):
raise PersistenceBacklogError("budget needs ceilings and baseline_observation objects")
for field in CEILING_FIELDS:
ceiling = non_negative_integer(ceilings.get(field), f"ceilings.{field}")View on GitHub (pinned to 8880682c63)
Solutions
- Run the checker without --budget so it loads the default scripts/persistence-backlog-budget.json
- In the custom budget file, set document_kind to exactly 'codewhale.persistence_backlog_budget'
- Check for whitespace, case, or trailing-character differences when copying the kind string
Example fix
// before (custom-budget.json) "document_kind": "persistence_backlog_budget" // after "document_kind": "codewhale.persistence_backlog_budget"
Defensive patterns
Strategy: validation
Validate before calling
BUDGET_KIND = "codewhale.persistence_backlog_budget"
def is_budget_doc(doc: dict) -> bool:
return isinstance(doc, dict) and doc.get("document_kind") == BUDGET_KIND Type guard
from typing import TypeGuard
def is_budget_doc(doc: object) -> TypeGuard[dict]:
return isinstance(doc, dict) and doc.get("document_kind") == "codewhale.persistence_backlog_budget" Prevention
- Load budgets from the repo checkout (scripts/persistence-backlog-budget.json) instead of hand-maintained copies
- Validate budget JSON with python -m json.tool and a key-set check before running the checker
- Change FIXTURE/SCHEMA_VERSION in the checker only together with regenerating budget and baseline receipt in one commit
When it happens
Trigger: Running scripts/check-persistence-backlog-budget.py --budget <file> where document_kind is missing, misspelled, or holds another kind such as 'codewhale.persistence_backlog_receipt' (the receipt discriminator).
Common situations: Passing the receipt file to --budget by mistake; a schema migration renaming the document kind without regenerating budgets; copy-pasting a budget template that kept a placeholder kind.
Related errors
- budget fixture no longer matches the frozen workload
- budget baseline_receipt path changed
- budget needs ceilings and baseline_observation objects
- rss_during_delta_bytes is inconsistent
- rss_after_delta_bytes is inconsistent
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/c0d242dbc1a0db3b.
Report an issue: GitHub.