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

  1. Store digest.hexdigest() (lowercase, 64 chars) from hashlib.sha256
  2. Fix the value to the exact 64-char lowercase hex string
  3. 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

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


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)