Hmbown/CodeWhale · error · RuntimeContractError
field ` ` must be a lowercase SHA-256 digest
Error message
{kind} field `{'.'.join(path)}` must be a lowercase SHA-256 digest What it means
Each representative_context.stages.<stage>.identity_sha256 must be a 64-character lowercase hex string, i.e. a canonical SHA-256 digest. This is a format check (not a value check) ensuring digests are copyable and comparable across receipts.
Solutions
- Store digest.hexdigest() (lowercase, 64 chars) from hashlib.sha256
- Fix the value to the exact 64-char lowercase hex string
- Validate the format before writing: re.fullmatch(r"[0-9a-f]{64}", digest)
Example fix
// before "identity_sha256": "ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890" // after "identity_sha256": "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
Defensive patterns
Strategy: validation
Validate before calling
import re
for stage, _ in REPRESENTATIVE_STAGES:
d = doc["representative_context"]["stages"][stage]["identity_sha256"]
assert isinstance(d, str) and re.fullmatch(r"[0-9a-f]{64}", d), f"bad digest for {stage}" Type guard
def is_sha256_hex(v) -> bool:
return isinstance(v, str) and re.fullmatch(r"[0-9a-f]{64}", v) is not None Try / catch
try:
validate_receipt(receipt)
except RuntimeContractError as e:
if "lowercase SHA-256 digest" in str(e):
print("digest format invalid; store hashlib hexdigest() output")
raise Prevention
- Always use hashlib ...hexdigest(), never upper() or truncation
- Add is_sha256_hex to your document-loading helper
- Reject placeholder strings in templates before they reach receipts
When it happens
Trigger: A stage digest that is uppercase hex, shorter/longer than 64 chars, contains non-hex characters, or is not a string at all.
Common situations: Digest produced by hashlib.sha256().hexdigest().upper(); a truncated or truncated-prefixed digest; a placeholder string like "<sha256>" left in a template; digest written as bytes.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- accepted_requests must equal requests_attempted; sender…
- applied_version is not the final sent version
- AT-SPI action failed
- AT-SPI resolve failed
- baseline_observation.applied_version must be the final sent…
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/2e5b808ac3250d8c.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/check-runtime-contract-budget.py:250
count = metric_value(document, (*base, "tools"), kind)
if count != len(names):
raise RuntimeContractError(
f"{kind} metric `{'.'.join((*base, 'tools'))}` must equal the "
f"owned tool_names length ({len(names)})"
)
digest = required_value(document, (*base, "identity_sha256"), kind)
expected = tool_identity_digest(names)
if digest != expected:
raise RuntimeContractError(
f"{kind} field `{'.'.join((*base, 'identity_sha256'))}` must "
"match the owned sorted tool_names"
)
for stage, _label in REPRESENTATIVE_STAGES:
path = ("representative_context", "stages", stage, "identity_sha256")
digest = required_value(document, path, kind)
if not isinstance(digest, str) or re.fullmatch(r"[0-9a-f]{64}", digest) is None:
raise RuntimeContractError(
f"{kind} field `{'.'.join(path)}` must be a lowercase SHA-256 digest"
)
def validate_receipt(receipt: dict[str, Any]) -> None:
validate_document(receipt, RECEIPT_KIND, "receipt")
skill_discovery = receipt.get("skill_discovery")
identical = (
skill_discovery.get("prompts_byte_identical")
if isinstance(skill_discovery, dict)
else None
)
if identical is not True:
raise RuntimeContractError(
"receipt metric `skill_discovery.prompts_byte_identical` must be true"
)
representative = receipt.get("representative_context")
fixture_id = (View on GitHub (pinned to 433685b202)