headroomlabs-ai/headroom · error · RolloutConfigurationError
rollout worker policy version mismatch
Error message
rollout worker policy version mismatch
What it means
Raised by RolloutSnapshot.from_internal_dict() when the restored dict's 'policy_version' does not equal ROLLOUT_POLICY_VERSION. Independent of the wire schema version, this pins the rollout policy semantics (how channels/features resolve), so snapshots cross a policy change must be rebuilt rather than reinterpreted.
Source
Thrown at headroom/rollout.py:294
"channel": self.channel.value,
"unsafe_allow_unstable": self.unsafe_allow_unstable,
"explicit_requested": sorted(self.config.explicit_requested),
"explicit_disabled": sorted(self.config.explicit_disabled),
"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,View on GitHub (pinned to 322425c43b)
Solutions
- Upgrade all processes to the same headroom version so ROLLOUT_POLICY_VERSION matches.
- Regenerate the snapshot at the current process and re-handoff instead of restoring the stale one.
- Treat policy-version mismatch as a signal to rebuild from config, not to patch the dict.
Example fix
# before snapshot = RolloutSnapshot.from_internal_dict(stale_dict) # after # re-serialize from the current process after upgrading both sides snapshot = RolloutSnapshot.from_internal_dict(current.to_internal_dict())
Defensive patterns
Strategy: validation
Validate before calling
from headroom.rollout import ROLLOUT_POLICY_VERSION
if payload.get('policy_version') != ROLLOUT_POLICY_VERSION:
raise HandoffVersionError('policy version skew between producer and consumer') Type guard
def snapshot_policy_matches(payload: Mapping) -> bool:
from headroom.rollout import ROLLOUT_POLICY_VERSION
return payload.get('policy_version') == ROLLOUT_POLICY_VERSION Try / catch
try:
snapshot = RolloutSnapshot.from_internal_dict(payload)
except RolloutConfigurationError as e:
if 'policy version' in str(e):
snapshot = resolve_fresh_snapshot() # rebuild under current policy
else:
raise Prevention
- Treat policy-version mismatch as a rebuild signal, never patch the field in the dict.
- Coordinate headroom upgrades so all snapshot producers/consumers move together.
- Monitor for this error during canary deploys as a version-skew detector.
When it happens
Trigger: Restoring a snapshot produced under an older rollout policy — typically after upgrading headroom past a policy revision — or mutating the 'policy_version' field in a hand-built dict.
Common situations: Version skew between the process that serialized the snapshot and the one restoring it (rolling deploy, canary worker); cached/persisted snapshots surviving an upgrade; copy-pasted snapshot fixtures in tests.
Related errors
- unsupported rollout worker schema version
- invalid rollout worker snapshot
- rollout worker registry digest mismatch
- rollout worker snapshot digest mismatch
- Invalid semantic version: {value}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/f5f594fc81403a8c.
Report an issue: GitHub.