Hmbown/CodeWhale · error · PersistenceBacklogError
budget schema_version changed
Error message
budget schema_version changed
What it means
validate_budget rejects a budget whose schema_version does not equal SCHEMA_VERSION (2). The checker enforces a one-way schema: an old budget written against schema version 1 (or a future one) is not interpretable under the current contract. This prevents silently comparing a current receipt against a stale budget layout.
Solutions
- Update the budget's schema_version to 2 and regenerate its ceilings/baseline_observation per the new schema
- Re-run the measurement flow that produces the budget for the current schema
- Restore the budget file matching the checked-out script version from git
Example fix
// before
{ "schema_version": 1, ... }
// after
{ "schema_version": 2, ... } Defensive patterns
Strategy: validation
Validate before calling
budget = json.load(open("scripts/persistence-backlog-budget.json"))
assert budget.get("schema_version") == 2, f"budget schema is {budget.get('schema_version')}, script requires 2" Type guard
def is_current_schema(doc):
return isinstance(doc, dict) and doc.get("schema_version") == 2 Try / catch
try:
validate_budget(budget)
except PersistenceBacklogError as e:
if "schema_version changed" in str(e):
print("regenerate the budget for the current schema before checking")
raise Prevention
- After pulling script changes, regenerate or restore the committed budget in the same step
- Check schema_version before hand-editing a budget
- Keep budget regeneration and script schema bumps in one commit
When it happens
Trigger: compare calls validate_budget on scripts/persistence-backlog-budget.json (or a --budget override) whose schema_version field is absent or not 2, e.g. after the script bumped SCHEMA_VERSION without regenerating the committed budget.
Common situations: Pulling new code with an updated schema while an old local budget file remains; editing the budget by hand and dropping the field; cherry-picking a script change without its budget regeneration commit.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- baseline_observation.accepted_requests must equal…
- baseline_observation.
- Bound task identity or schema does not match its durable…
- budget baseline_receipt path changed
- budget document_kind must be
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/2acbeefa1c0e8b57.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/check-persistence-backlog-budget.py:246
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}")
observed = non_negative_integer(
baseline.get(field), f"baseline_observation.{field}"View on GitHub (pinned to 433685b202)