{"record":{"id":"df93b8d092b8299f","repo":"ruvnet/RuView","slug":"calibration-bundle-path-missing-key-key-r","errorCode":null,"errorMessage":"Calibration bundle {path} missing key {key!r}","messagePattern":"Calibration bundle (.+?) missing key (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scripts/calibration_lib.py","lineNumber":334,"sourceCode":"    \"\"\"\n    canonical = json.dumps(bundle, sort_keys=True, separators=(\",\", \":\"))\n    return \"sha256:\" + hashlib.sha256(canonical.encode(\"utf-8\")).hexdigest()\n\n\ndef save_bundle(bundle: dict, path: Path) -> None:\n    path = Path(path)\n    path.parent.mkdir(parents=True, exist_ok=True)\n    with open(path, \"w\", encoding=\"utf-8\") as f:\n        json.dump(bundle, f, indent=2)\n        f.write(\"\\n\")\n\n\ndef load_bundle(path: Path) -> dict:\n    with open(path, \"r\", encoding=\"utf-8\") as f:\n        bundle = json.load(f)\n    for key in (\"camera_intrinsics\", \"camera_to_room_extrinsics\", \"transceiver_geometry\"):\n        if key not in bundle:\n            raise ValueError(f\"Calibration bundle {path} missing key {key!r}\")\n    return bundle\n\n\n# ---------------------------------------------------------------------------\n# Keypoint transform (image -> room-frame bearing rays)\n# ---------------------------------------------------------------------------\n\nclass CalibrationContext:\n    \"\"\"Pre-computed transform state for a collection session.\n\n    Scales the bundle's intrinsics to the live capture resolution (MediaPipe\n    keypoints are normalized [0,1], so we need the actual frame size to get\n    back to pixels before undistorting).\n    \"\"\"\n\n    def __init__(self, bundle: dict, frame_w: int, frame_h: int):\n        self.bundle = bundle\n        self.calibration_id = calibration_id(bundle)","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/scripts/calibration_lib.py#L316-L352","documentation":"load_bundle() in scripts/calibration_lib.py reads a camera-room calibration bundle (the JSON that scripts/calibrate-camera-room.py writes via save_bundle) and validates that it contains the three keys the ADR-152 pipeline requires: camera_intrinsics, camera_to_room_extrinsics, and transceiver_geometry. It raises ValueError on the first key that is absent. The bundle couples camera intrinsics/extrinsics with WiFi transceiver geometry so every training label can be stamped with the deployment layout.","triggerScenarios":"Calling load_bundle(path) — e.g. scripts/collect-ground-truth.py --calibration bundle.json — on a JSON file that parses successfully but lacks one of the three required keys. The file itself is fine JSON; only the schema check fails.","commonSituations":"A hand-edited bundle where a section was renamed or removed; a bundle produced by an older version of the calibration tool before transceiver_geometry was added to the schema; passing a generic intrinsics-only JSON exported from another calibration tool instead of the two-checkerboard bundle.","solutions":["Regenerate the bundle with scripts/calibrate-camera-room.py, which writes all three keys via cal.save_bundle()","Inspect what you actually have: python -c \"import json; print(sorted(json.load(open('bundle.json'))))\" and compare against the three exact snake_case key names","If hand-authoring is unavoidable, include camera_intrinsics, camera_to_room_extrinsics, and transceiver_geometry exactly as spelled in the loop","Verify you passed the intended path — an unrelated or partial JSON file is the usual culprit"],"exampleFix":"# before\ncalib = cal.load_bundle(Path(\"my_intrinsics.json\"))  # ValueError: missing 'transceiver_geometry'\n\n# after\nimport json, pathlib\np = pathlib.Path(\"my_intrinsics.json\")\nkeys = set(json.loads(p.read_text()))\nmissing = {\"camera_intrinsics\", \"camera_to_room_extrinsics\", \"transceiver_geometry\"} - keys\nif missing:\n    raise SystemExit(f\"{p} missing {sorted(missing)}; regenerate with scripts/calibrate-camera-room.py\")\ncalib = cal.load_bundle(p)","handlingStrategy":"validation","validationCode":"import json\nfrom pathlib import Path\n\nREQUIRED_BUNDLE_KEYS = {\"camera_intrinsics\", \"camera_to_room_extrinsics\", \"transceiver_geometry\"}\n\ndef bundle_is_complete(path: Path) -> bool:\n    try:\n        keys = set(json.loads(Path(path).read_text(encoding=\"utf-8\")))\n    except (OSError, json.JSONDecodeError):\n        return False\n    return REQUIRED_BUNDLE_KEYS <= keys\n\n# before load_bundle:\n# assert bundle_is_complete(my_bundle) or regenerate","typeGuard":null,"tryCatchPattern":"try:\n    bundle = cal.load_bundle(path)\nexcept ValueError as e:\n    raise SystemExit(f\"bad calibration bundle {path}: {e}; regenerate with scripts/calibrate-camera-room.py\") from e","preventionTips":["Always produce bundles with scripts/calibrate-camera-room.py (save_bundle) instead of hand-writing JSON","Keep bundles with the collection data they belong to, since labels are stamped with the calibration","Add the three-key check to collection-script startup so a bad bundle fails before any capture session"],"tags":["calibration","json","schema","validation","python","scripts"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}