Hmbown/CodeWhale · error · PersistenceBacklogError
receipt source_sha must be an exact lowercase Git SHA
Error message
receipt source_sha must be an exact lowercase Git SHA
What it means
Raised in validate_receipt (scripts/check-persistence-backlog-budget.py:153-156) when source_sha is not a string or does not fully match SOURCE_SHA_PATTERN ([0-9a-f]{40}). The checker only accepts an exact 40-character lowercase hex SHA-1 commit id, since that string is compared verbatim against `git rev-parse HEAD` for provenance pinning.
Source
Thrown at scripts/check-persistence-backlog-budget.py:156
*,
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",
"source_dirty",
"rustc_version",
"cargo_version",
"build_profile",
"sample_count",
):
if receipt[field] != expected_source[field]:
raise PersistenceBacklogError(View on GitHub (pinned to 8880682c63)
Solutions
- Regenerate the receipt with scripts/measure-persistence-backlog.py so source_sha is captured verbatim from `git rev-parse HEAD`.
- Never abbreviate or recase the SHA when moving receipt data.
- Use a standard SHA-1 object-format repository for measurements (the 40-hex pattern rejects SHA-256 repos).
Example fix
// receipt (before) "source_sha": "9F86D0818..." // receipt (after) "source_sha": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b"
Defensive patterns
Strategy: type-guard
Validate before calling
import re
sha = receipt.get("source_sha")
if not isinstance(sha, str) or not re.fullmatch(r"[0-9a-f]{40}", sha):
sys.exit("source_sha malformed; recapture from `git rev-parse HEAD` verbatim") Type guard
def is_exact_sha(value) -> bool:
return isinstance(value, str) and re.fullmatch(r"[0-9a-f]{40}", value) is not None Try / catch
try:
validate_receipt(receipt)
except PersistenceBacklogError as e:
if "lowercase Git SHA" in str(e):
raise RuntimeError("provenance SHA mangled (SHA-256 repo or reformatting); re-measure") from e
raise Prevention
- Never abbreviate, recase, or synthesize the SHA; capture `git rev-parse HEAD` output verbatim.
- Run measurements in SHA-1 object-format repositories (the pattern rejects 64-hex).
- Keep env plumbing (CODEWHALE_TEST_PERSISTENCE_BACKLOG_SOURCE_SHA) byte-exact.
When it happens
Trigger: source_sha recorded as uppercase hex, a short SHA, an empty string or placeholder ("unknown", "dev"), a non-string value, or a 64-hex SHA from a repository using git's SHA-256 object format.
Common situations: Hand-filling provenance fields; tools that abbreviate SHAs; experimental SHA-256 repos; env-var plumbing (CODEWHALE_TEST_PERSISTENCE_BACKLOG_SOURCE_SHA) that dropped or altered the value.
Related errors
- receipt {field} does not match the checked source
- expected revision must be an exact 40-character Git SHA
- {context}: expected 'Name <id+login@users.noreply.github.com
- {context}: right-hand email must be numeric GitHub noreply,
- {path}:{lineno}: expected 'alias = Name <email>'
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/1c3201be68b0c1ba.
Report an issue: GitHub.