Hmbown/CodeWhale · error · RuntimeContractError
receipt and budget must resolve to distinct filesystem paths
Error message
receipt and budget must resolve to distinct filesystem paths
What it means
main() refuses to run when --receipt and --budget resolve (Path.resolve()) to the same file. Comparing a receipt against itself would trivially pass every ceiling, and combined with --update the tool would overwrite the receipt with budget JSON, destroying the measurement evidence. Symlinks and './' versus absolute spellings of the same file are caught because resolve() normalizes them.
Source
Thrown at scripts/check-runtime-contract-budget.py:635
help="check an existing measurement JSON instead of compiling",
)
parser.add_argument(
"--budget",
type=Path,
default=BUDGET_PATH,
help=argparse.SUPPRESS,
)
parser.add_argument(
"--update",
action="store_true",
help="tighten all ceilings to the current receipt; refuses increases",
)
args = parser.parse_args(argv)
try:
check_fragment_caps()
if args.receipt is not None and args.receipt.resolve() == args.budget.resolve():
raise RuntimeContractError(
"receipt and budget must resolve to distinct filesystem paths"
)
budget = load_json(args.budget, "budget")
receipt = (
load_json(args.receipt, "receipt")
if args.receipt is not None
else run_measurement()
)
increases, decreases = compare(receipt, budget)
except RuntimeContractError as error:
print(f"[runtime-contract-budget] ERROR: {error}", file=sys.stderr)
return 2
if increases:
print("[runtime-contract-budget] FAIL: runtime contract grew:", file=sys.stderr)
for path, label, current, ceiling in increases:
print(
f" {label}: {current} > {ceiling} (+{current - ceiling}) [{path}]",View on GitHub (pinned to 8880682c63)
Solutions
- Pass distinct files: keep the budget at scripts/runtime-contract-budget.json and point --receipt at a freshly measured receipt from measure-runtime-contract.py
- If aliasing was accidental (symlink or relative-path normalization), pass the real distinct paths
- In wrapper scripts, assert Path(receipt).resolve() != Path(budget).resolve() before invoking the checker
Example fix
# before python3 scripts/check-runtime-contract-budget.py --receipt scripts/runtime-contract-budget.json # after python3 scripts/measure-runtime-contract.py > /tmp/receipt.json python3 scripts/check-runtime-contract-budget.py --receipt /tmp/receipt.json
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path receipt, budget = Path(args.receipt), Path(args.budget) assert receipt.resolve() != budget.resolve(), "receipt and budget must be distinct files"
Type guard
def is_runtime_contract_error(exc: BaseException) -> bool:
return isinstance(exc, ValueError) and type(exc).__name__ == "RuntimeContractError" Try / catch
try:
rc = main(["--receipt", str(receipt)])
except RuntimeContractError as error:
print(f"[gate] {error}", file=sys.stderr)
raise SystemExit(2) Prevention
- Always generate a fresh receipt with measure-runtime-contract.py instead of reusing the budget file
- In wrappers, resolve() both paths and assert distinctness before invoking
- Never combine --receipt pointing at scripts/runtime-contract-budget.json with --update - it would clobber the input
When it happens
Trigger: '--receipt scripts/runtime-contract-budget.json' (identical to the default budget path); '--receipt r.json --budget r.json'; a symlinked receipt pointing at the budget file.
Common situations: Copy-pasting commands from docs; scripted invocations that reuse one path variable for both flags; passing a copied budget as a 'receipt' to skip measuring.
Related errors
- Invalid GitHub repository: ${repo}
- Invalid release tag: ${tag}
- unknown argument: ${arg}
- unknown argument: ${arg}
- --days must be an integer from 1 through 90
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/362646183380008b.
Report an issue: GitHub.