ruvnet/RuView · error · ValueError
invalid privacy class {s!r}; expected one of {list(m.keys())
Error message
invalid privacy class {s!r}; expected one of {list(m.keys())} What it means
PrivacyClass.from_str parses the --privacy-class CLI/config value into the integer privacy classes used by the ADR-125 §2.1.d HomeKit/HAP gate. Only raw, derived, anonymous, restricted (case-insensitive) are accepted; any other string raises ValueError listing the valid set. Only anonymous (2) and restricted (3) may cross the HAP boundary (allows_hap).
Source
Thrown at scripts/c6-presence-watcher.py:82
"""
RAW = 0
DERIVED = 1
ANONYMOUS = 2
RESTRICTED = 3
_names = {RAW: "Raw", DERIVED: "Derived", ANONYMOUS: "Anonymous",
RESTRICTED: "Restricted"}
@classmethod
def name(cls, value: int) -> str:
return cls._names.get(value, f"Unknown({value})")
@classmethod
def from_str(cls, s: str) -> int:
m = {"raw": cls.RAW, "derived": cls.DERIVED,
"anonymous": cls.ANONYMOUS, "restricted": cls.RESTRICTED}
if s.lower() not in m:
raise ValueError(f"invalid privacy class {s!r}; "
f"expected one of {list(m.keys())}")
return m[s.lower()]
@classmethod
def allows_hap(cls, value: int) -> bool:
"""ADR-125 §2.1.d gate: only class-2/3 cross the HomeKit boundary."""
return value in (cls.ANONYMOUS, cls.RESTRICTED)
# Semantic-event naming per ADR-125 §2.1.d. The HAP bridge keeps
# advertising a generic MotionSensor; this is the operator-facing
# *label* for the event, written into the watcher log + summary line
# so the operator never sees "intruder detected" framing.
SEMANTIC_EVENT_UNKNOWN_PRESENCE = "Unknown Presence"
# Hysteresis — entry / exit thresholds keep the HomeKit characteristic
# from flapping when presence_score sits near the boundary.
PRESENCE_ON_THRESHOLD = 0.40View on GitHub (pinned to 4685618388)
Solutions
- Use one of raw, derived, anonymous, restricted (the CLI default is anonymous)
- For HomeKit exposure choose anonymous or restricted — raw/derived fail the allows_hap gate and the watcher refuses to start
- Fix the calling script/config that produced the invalid token
Example fix
# before python scripts/c6-presence-watcher.py --privacy-class public # ValueError # after python scripts/c6-presence-watcher.py --privacy-class anonymous
Defensive patterns
Strategy: validation
Validate before calling
VALID_PRIVACY = {"raw", "derived", "anonymous", "restricted"}
def validate_privacy_class(value: str) -> str:
if value.lower() not in VALID_PRIVACY:
raise SystemExit(
f"invalid privacy class {value!r}; "
f"expected one of {sorted(VALID_PRIVACY)}"
)
return value.lower() Type guard
def is_valid_privacy_class(s: str) -> bool:
return isinstance(s, str) and s.lower() in {
"raw", "derived", "anonymous", "restricted"
} Try / catch
try:
privacy_class = PrivacyClass.from_str(raw_value)
except ValueError as e:
raise SystemExit(f"bad --privacy-class value: {e}") from e Prevention
- Validate config values at load time, before the watcher starts
- Keep valid class names in one constants module shared by wrappers
- Remember the HAP gate: only anonymous/restricted are HomeKit-eligible
When it happens
Trigger: `python scripts/c6-presence-watcher.py --privacy-class public` (or 'anon', 'PII', any non-listed token); an automation or config file feeding an old/renamed class name into from_str at line 213.
Common situations: Renamed classes after an ADR update; typos in wrapper scripts; runbooks with stale example commands.
Related errors
- {path}: expected {{'nodes': [...]}} or a top-level list
- Threshold must be between 0.0 and 1.0
- FPS must be between 1 and 60
- Compression level must be between 1 and 9
- Failed to load domain configuration: {e}
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/93b72b7bede0ba7a.
Report an issue: GitHub.