headroomlabs-ai/headroom · error · RolloutConfigurationError
invalid rollout worker unsafe override
Error message
invalid rollout worker unsafe override
What it means
Raised by RolloutSnapshot.from_internal_dict() when the 'unsafe_allow_unstable' field is present but not a bool (e.g. the string 'true' or an int 1). Because this flag bypasses stability protections, the restore path requires an actual JSON boolean rather than a truthy value of another type.
Source
Thrown at headroom/rollout.py:298
"legacy_requested": sorted(self.config.legacy_requested),
"legacy_disabled": sorted(self.config.legacy_disabled),
}
@classmethod
def from_internal_dict(cls, value: Mapping[str, object]) -> RolloutSnapshot:
"""Validate and restore a snapshot serialized for worker handoff."""
if not isinstance(value, Mapping):
raise RolloutConfigurationError("invalid rollout worker snapshot")
try:
if value.get("schema_version") != ROLLOUT_SCHEMA_VERSION:
raise RolloutConfigurationError("unsupported rollout worker schema version")
if value.get("policy_version") != ROLLOUT_POLICY_VERSION:
raise RolloutConfigurationError("rollout worker policy version mismatch")
channel = RolloutChannel.parse(str(value["channel"]), strict=True)
unsafe = value["unsafe_allow_unstable"]
if not isinstance(unsafe, bool):
raise RolloutConfigurationError("invalid rollout worker unsafe override")
def names(field: str) -> set[str]:
raw = value[field]
if not isinstance(raw, list) or not all(isinstance(item, str) for item in raw):
raise RolloutConfigurationError(f"invalid rollout worker field {field!r}")
return set(_validate_names(set(raw), source=field, strict=True))
snapshot = _resolve_snapshot(
channel=channel,
explicit_requested=names("explicit_requested"),
explicit_disabled=names("explicit_disabled"),
legacy_requested=names("legacy_requested"),
legacy_disabled=names("legacy_disabled"),
unsafe=unsafe,
)
except (KeyError, TypeError) as exc:
raise RolloutConfigurationError("invalid rollout worker snapshot") from exc
if value.get("registry_digest") != snapshot.registry_digest:View on GitHub (pinned to 322425c43b)
Solutions
- Produce handoff dicts via to_internal_dict() so the field is a real bool.
- Convert strings before restore: unsafe in (True, False) or bool parsing in your adapter.
- Never inject env-var strings directly into the handoff payload.
Example fix
# before
payload['unsafe_allow_unstable'] = os.environ.get('UNSAFE', 'false')
# after
payload['unsafe_allow_unstable'] = os.environ.get('UNSAFE', 'false').lower() == 'true' Defensive patterns
Strategy: type-guard
Validate before calling
unsafe = payload.get('unsafe_allow_unstable')
if not isinstance(unsafe, bool):
raise ValueError('unsafe_allow_unstable must be a bool') Type guard
def is_bool_field(value: object) -> bool:
return isinstance(value, bool) # note: True/1 are distinct in isinstance(bool, ...) Try / catch
try:
snapshot = RolloutSnapshot.from_internal_dict(payload)
except RolloutConfigurationError as e:
if 'unsafe override' in str(e):
payload['unsafe_allow_unstable'] = bool(payload['unsafe_allow_unstable'])
snapshot = RolloutSnapshot.from_internal_dict(payload)
else:
raise Prevention
- Never place env-var strings into handoff payloads; coerce to real booleans first.
- Serialize with to_internal_dict() so types are correct by construction.
- Validate payload types with a JSON schema (additionalProperties with types) at the producer.
When it happens
Trigger: from_internal_dict({'unsafe_allow_unstable': 'true', ...}) or 1/0 ints — typical when the dict was built from env vars or form data instead of to_internal_dict().
Common situations: Serializing a snapshot with values sourced from environment variables (always strings); a worker framework coercing booleans to ints; hand-written test fixtures.
Related errors
- invalid rollout worker field {field!r}
- invalid rollout worker snapshot
- unsupported rollout worker schema version
- unknown rollout channel {value!r}
- rollout worker policy version mismatch
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/55d5be54bebbb2bd.
Report an issue: GitHub.