Hmbown/CodeWhale · error · RuntimeContractError
measurement emitted invalid JSON: {error}
Error message
measurement emitted invalid JSON: {error} What it means
After a successful measurement, run_measurement() parses the child's entire stdout as JSON to obtain the receipt. If json.loads raises, the raw stdout contained something non-JSON - the receipt printer's output was polluted or truncated. The JSONDecodeError detail (line/column) is embedded in the message to point at the offending byte.
Source
Thrown at scripts/check-runtime-contract-budget.py:411
env["CARGO_NET_OFFLINE"] = "true"
proc = subprocess.run(
[sys.executable, str(MEASURE_SCRIPT)],
cwd=REPO_ROOT,
env=env,
capture_output=True,
text=True,
check=False,
)
sys.stderr.write(proc.stderr)
if proc.returncode != 0:
sys.stdout.write(proc.stdout)
raise RuntimeContractError(
f"runtime-contract measurement failed with exit code {proc.returncode}"
)
try:
receipt = json.loads(proc.stdout)
except json.JSONDecodeError as error:
raise RuntimeContractError(f"measurement emitted invalid JSON: {error}") from error
if not isinstance(receipt, dict):
raise RuntimeContractError("measurement top level must be an object")
validate_receipt(receipt)
return receipt
def update_command(receipt_path: Path | None, budget_path: Path) -> str:
parts = ["python3", "scripts/check-runtime-contract-budget.py"]
if receipt_path is not None:
parts.extend(["--receipt", str(receipt_path)])
if budget_path != BUDGET_PATH:
parts.extend(["--budget", str(budget_path)])
parts.append("--update")
return shlex.join(parts)
FRAGMENT_MODULE = REPO_ROOT / "crates" / "core" / "src" / "fragments.rs"
FRAGMENT_MAX_TOKENS_CEILING = 10_000View on GitHub (pinned to 8880682c63)
Solutions
- Reproduce and capture: python3 scripts/measure-runtime-contract.py > out.json and inspect around the reported line/column
- Route every diagnostic in the measure path to stderr: print(..., file=sys.stderr) in Python, eprintln! in Rust
- Pipe the stdout through python3 -m json.tool as a quick validity check before wiring changes back into the gate
Example fix
# before (measure path)
print(f"measuring {name}") # pollutes stdout, breaks json.loads
# after
import sys
print(f"measuring {name}", file=sys.stderr) Defensive patterns
Strategy: try-catch
Validate before calling
import json, subprocess, sys
def measurement_stdout_is_json() -> bool:
proc = subprocess.run(
[sys.executable, "scripts/measure-runtime-contract.py"],
capture_output=True,
text=True,
)
if proc.returncode != 0:
return False
try:
json.loads(proc.stdout)
return True
except json.JSONDecodeError:
return False Try / catch
try:
receipt = mod.run_measurement()
except mod.RuntimeContractError as err:
if "invalid JSON" in str(err):
import json
proc = subprocess.run(
[sys.executable, "scripts/measure-runtime-contract.py"],
capture_output=True,
text=True,
)
try:
json.loads(proc.stdout)
except json.JSONDecodeError as e:
print("offending stdout near:", repr(proc.stdout[max(0, e.pos - 80): e.pos + 80]))
raise SystemExit(2) Prevention
- Route all diagnostics in the measurement path to stderr (eprintln! / print(..., file=sys.stderr))
- Keep cargo and build progress off the captured stdout pipe (cargo writes progress to stderr, wrappers may not)
- Assert stdout purity in the measure script's own tests: parse your own output before exiting
When it happens
Trigger: The --nocapture test or the measure script printing diagnostics to stdout (println!/print) instead of stderr; a panic message interleaved into stdout; partial output when the child dies mid-write while still exiting 0; progress bars or cargo notes leaking into the captured pipe.
Common situations: A developer adds a debug println! in the metric test and the gate suddenly fails locally; a dependency upgrades and starts writing to stdout; running with a wrapper (rustfilt, backtrace pretty-printers) that injects text.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- measurement emitted invalid JSON: {error}
- baseline provenance build profile/sample count changed
- baseline receipt {field} does not match baseline_observation
- baseline receipt {field} does not match baseline provenance
- measurement command failed
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/d5811f5eafd4ea60.
Report an issue: GitHub.