Hmbown/CodeWhale · error · RuntimeContractError

metric ` ` must equal the owned tool_names length ( )

Error message

{kind} metric `{'.'.join((*base, 'tools'))}` must equal the owned tool_names length ({len(names)})

What it means

Each mode/surface section carries a tools count metric that must equal len(tool_names) in the same section. This cross-check catches drift between the human-readable list and the numeric metric used by budget comparisons.

Solutions

  1. Set tools to exactly len(tool_names) for that section
  2. Regenerate the receipt so both are written from the same source of truth
  3. Fix the generator to derive the count from the list rather than tracking it separately

Example fix

// before
"tool_names": ["a", "b"], "tools": 3
// after
"tool_names": ["a", "b"], "tools": 2
Defensive patterns

Strategy: validation

Validate before calling

for mode, _ in VISIBLE_MODES:
    for surface, _ in TOOL_SURFACES:
        sec = doc["tool_catalog"]["modes"][mode][surface]
        assert sec["tools"] == len(sec["tool_names"]), f"count drift in {mode}/{surface}"

Try / catch

try:
    compare(receipt, budget)
except RuntimeContractError as e:
    if "must equal the owned tool_names length" in str(e):
        print("count/list drift; regenerate the receipt")
    raise

Prevention

When it happens

Trigger: metric_value(document, (*base, "tools"), kind) returns a number different from the length of the sibling tool_names list — e.g. the count was updated but the list was not, or vice versa.

Common situations: Hand-edited receipts where a tool was added to the list but the count not incremented; two generators writing list and count at different times; merge conflict resolved on one side only.

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


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/e82ca4903cf483af. Report an issue: GitHub.

Appendix: source

Thrown at scripts/check-runtime-contract-budget.py:234

            f"{kind} tool execution_shell must be `bash`, got {shell!r}"
        )

    for mode, _label in VISIBLE_MODES:
        for surface, _surface_label in TOOL_SURFACES:
            base = ("tool_catalog", "modes", mode, surface)
            names = required_value(document, (*base, "tool_names"), kind)
            dotted_names = ".".join((*base, "tool_names"))
            if (
                not isinstance(names, list)
                or any(not isinstance(name, str) or not name for name in names)
                or names != sorted(set(names))
            ):
                raise RuntimeContractError(
                    f"{kind} field `{dotted_names}` must be sorted unique non-empty strings"
                )
            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"
            )

View on GitHub (pinned to 433685b202)