ruvnet/RuView · error · ValueError

Calibration bundle {path} missing key {key!r}

Error message

Calibration bundle {path} missing key {key!r}

What it means

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.

Source

Thrown at scripts/calibration_lib.py:334

    """
    canonical = json.dumps(bundle, sort_keys=True, separators=(",", ":"))
    return "sha256:" + hashlib.sha256(canonical.encode("utf-8")).hexdigest()


def save_bundle(bundle: dict, path: Path) -> None:
    path = Path(path)
    path.parent.mkdir(parents=True, exist_ok=True)
    with open(path, "w", encoding="utf-8") as f:
        json.dump(bundle, f, indent=2)
        f.write("\n")


def load_bundle(path: Path) -> dict:
    with open(path, "r", encoding="utf-8") as f:
        bundle = json.load(f)
    for key in ("camera_intrinsics", "camera_to_room_extrinsics", "transceiver_geometry"):
        if key not in bundle:
            raise ValueError(f"Calibration bundle {path} missing key {key!r}")
    return bundle


# ---------------------------------------------------------------------------
# Keypoint transform (image -> room-frame bearing rays)
# ---------------------------------------------------------------------------

class CalibrationContext:
    """Pre-computed transform state for a collection session.

    Scales the bundle's intrinsics to the live capture resolution (MediaPipe
    keypoints are normalized [0,1], so we need the actual frame size to get
    back to pixels before undistorting).
    """

    def __init__(self, bundle: dict, frame_w: int, frame_h: int):
        self.bundle = bundle
        self.calibration_id = calibration_id(bundle)

View on GitHub (pinned to 4685618388)

Solutions

  1. Regenerate the bundle with scripts/calibrate-camera-room.py, which writes all three keys via cal.save_bundle()
  2. 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
  3. If hand-authoring is unavoidable, include camera_intrinsics, camera_to_room_extrinsics, and transceiver_geometry exactly as spelled in the loop
  4. Verify you passed the intended path — an unrelated or partial JSON file is the usual culprit

Example fix

# before
calib = cal.load_bundle(Path("my_intrinsics.json"))  # ValueError: missing 'transceiver_geometry'

# after
import json, pathlib
p = pathlib.Path("my_intrinsics.json")
keys = set(json.loads(p.read_text()))
missing = {"camera_intrinsics", "camera_to_room_extrinsics", "transceiver_geometry"} - keys
if missing:
    raise SystemExit(f"{p} missing {sorted(missing)}; regenerate with scripts/calibrate-camera-room.py")
calib = cal.load_bundle(p)
Defensive patterns

Strategy: validation

Validate before calling

import json
from pathlib import Path

REQUIRED_BUNDLE_KEYS = {"camera_intrinsics", "camera_to_room_extrinsics", "transceiver_geometry"}

def bundle_is_complete(path: Path) -> bool:
    try:
        keys = set(json.loads(Path(path).read_text(encoding="utf-8")))
    except (OSError, json.JSONDecodeError):
        return False
    return REQUIRED_BUNDLE_KEYS <= keys

# before load_bundle:
# assert bundle_is_complete(my_bundle) or regenerate

Try / catch

try:
    bundle = cal.load_bundle(path)
except ValueError as e:
    raise SystemExit(f"bad calibration bundle {path}: {e}; regenerate with scripts/calibrate-camera-room.py") from e

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16). Data as JSON: /api/errors/df93b8d092b8299f. Report an issue: GitHub.