Hmbown/CodeWhale · error · RuntimeContractError
field ` ` must be sorted unique non-empty strings
Error message
{kind} field `{dotted_names}` must be sorted unique non-empty strings What it means
For each visible mode/tool-surface pair, the owned tool_names list must be a list of non-empty strings, sorted, and free of duplicates. validate_identity_structure enforces this so the identity digest (error 805) is deterministic. Anything unsorted, duplicated, empty, or non-string fails.
Solutions
- Sort the list and deduplicate: names = sorted(set(names)) in the generator before writing
- Remove empty or non-string entries from tool_names
- Regenerate the receipt with the current generator instead of editing by hand
Example fix
// before "tool_names": ["read", "edit", "read"] // after "tool_names": ["edit", "read"]
Defensive patterns
Strategy: validation
Validate before calling
names = doc["tool_catalog"]["modes"][mode][surface]["tool_names"]
ok = (isinstance(names, list)
and all(isinstance(n, str) and n for n in names)
and names == sorted(set(names)))
assert ok, "tool_names must be sorted unique non-empty strings" Type guard
def valid_tool_names(v) -> bool:
return (isinstance(v, list)
and all(isinstance(n, str) and n for n in v)
and v == sorted(set(v))) Try / catch
try:
validate_receipt(receipt)
except RuntimeContractError as e:
if "sorted unique non-empty strings" in str(e):
print("regenerate: generator emitted unsorted or duplicated tool_names")
raise Prevention
- In generators, always write sorted(set(names))
- Reject empty tool names at registration time
- Add a pre-write assertion in the generator mirroring this rule
When it happens
Trigger: A tool_catalog.modes.<mode>.<surface>.tool_names array in a receipt/budget that is unsorted, contains duplicates, contains empty strings, or contains non-string entries.
Common situations: Generator appends tools in discovery order rather than sorted; duplicate registration of a tool; a tool with an empty name after a rename; hand-edited list.
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
- Codewhale metadata event was not a terminal receipt
- field ` ` must match the owned sorted tool_names
- is missing required field
- metric ` ` must equal the owned tool_names length ( )
- tool execution_shell must be `bash`, got
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/d988d5b824e8d25e.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/check-runtime-contract-budget.py:229
)
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):
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")View on GitHub (pinned to 433685b202)