Hmbown/CodeWhale · error · RuntimeContractError
tool execution_shell must be `bash`, got
Error message
{kind} tool execution_shell must be `bash`, got {shell!r} What it means
The contract requires the tool catalog to declare bash as its execution shell; any other value makes the measurement non-reproducible against the pinned contract. validate_identity_structure compares tool_catalog.execution_shell to the literal "bash" and throws otherwise.
Solutions
- Set tool_catalog.execution_shell to "bash" in the document
- Regenerate the receipt in a bash environment using the current script
- If a non-bash shell is genuinely required, that is a contract change: update the script and all receipts together
Example fix
// before
{"tool_catalog": {"execution_shell": "sh"}}
// after
{"tool_catalog": {"execution_shell": "bash"}} Defensive patterns
Strategy: validation
Validate before calling
assert doc.get("tool_catalog", {}).get("execution_shell") == "bash", \
"receipt must declare bash as execution_shell" Try / catch
try:
validate_budget(budget)
except RuntimeContractError as e:
if "execution_shell" in str(e):
raise SystemExit("receipt generated for a non-bash shell; regenerate in bash")
raise Prevention
- Run measurement scripts with bash (set SHELL or invoke via bash explicitly)
- Assert execution_shell == "bash" right after loading any receipt
- Reject non-bash shells at generator time, not at validation time
When it happens
Trigger: validate_receipt/validate_budget reading a document whose tool_catalog.execution_shell is not exactly "bash" (e.g. "sh", "zsh", null).
Common situations: Receipt produced on/for a different shell environment; hand-edited document; generator configured with a non-bash shell.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Codewhale metadata event was not a terminal receipt
- field ` ` must be sorted unique non-empty strings
- field ` ` must match the owned sorted tool_names
- is missing required field
- metric ` ` must equal the owned tool_names length ( )
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/0c23c934d9f0bce6.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/check-runtime-contract-budget.py:215
value = value[part]
return value
def tool_identity_digest(names: list[str]) -> str:
return hashlib.sha256("\0".join(names).encode("utf-8")).hexdigest()
def validate_identity_structure(document: dict[str, Any], kind: str) -> None:
profile = required_value(document, ("tool_catalog", "surface_profile"), kind)
if profile != TOOL_SURFACE_PROFILE:
raise RuntimeContractError(
f"{kind} tool surface_profile must be `{TOOL_SURFACE_PROFILE}`, "
f"got {profile!r}"
)
shell = required_value(document, ("tool_catalog", "execution_shell"), kind)
if shell != "bash":
raise RuntimeContractError(
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):View on GitHub (pinned to 433685b202)