headroomlabs-ai/headroom · error · RolloutConfigurationError
unknown rollout channel {value!r}
Error message
unknown rollout channel {value!r} What it means
Raised by RolloutChannel.parse() in strict mode when the value is neither a valid enum member nor one of the aliases ('production', 'preview', 'nightly', 'development'), after lowercasing. In non-strict mode it only logs a warning and falls back to STABLE, so the exception surfaces only when the caller demands strict validation (e.g. worker snapshot restore).
Source
Thrown at headroom/rollout.py:59
def parse(cls, value: str | None, *, strict: bool = False) -> RolloutChannel:
if not value:
return cls.STABLE
normalized = value.strip().lower().replace("-", "_")
aliases = {
"prod": cls.STABLE,
"production": cls.STABLE,
"preview": cls.BETA,
"nightly": cls.CANARY,
"development": cls.DEV,
}
if normalized in aliases:
return aliases[normalized]
try:
return cls(normalized)
except ValueError:
message = f"unknown rollout channel {value!r}"
if strict:
raise RolloutConfigurationError(message) from None
logger.warning("%s; falling back to 'stable'", message)
return cls.STABLE
@property
def order(self) -> int:
return {
RolloutChannel.STABLE: 0,
RolloutChannel.BETA: 1,
RolloutChannel.CANARY: 2,
RolloutChannel.DEV: 3,
}[self]
def allows(self, required: RolloutChannel) -> bool:
return self.order >= required.order
class FeatureDecisionReason(str, Enum):
DEFAULT = "default"View on GitHub (pinned to 322425c43b)
Solutions
- Use a canonical channel name: 'stable', 'beta', 'canary', 'dev', or an alias 'production'/'preview'/'nightly'/'development'.
- Normalize your config's channel vocabulary to these names before parse().
- If a bad channel should not be fatal, call parse() without strict=True and accept the STABLE fallback (a warning is logged).
Example fix
# before
channel = RolloutChannel.parse(cfg['channel'], strict=True) # 'prod'
# after
channel = RolloutChannel.parse('production', strict=True) Defensive patterns
Strategy: validation
Validate before calling
ALIASES = {'stable', 'beta', 'canary', 'dev', 'production', 'preview', 'nightly', 'development'}
normalized = channel.strip().lower()
if normalized not in ALIASES:
raise ConfigError(f'unknown rollout channel: {channel!r}')
parsed = RolloutChannel.parse(channel, strict=True) Type guard
def is_rollout_channel(value: str) -> bool:
v = (value or '').strip().lower()
aliases = {'stable', 'beta', 'canary', 'dev', 'production', 'preview', 'nightly', 'development'}
return v in aliases Try / catch
from headroom.rollout import RolloutChannel, RolloutConfigurationError
try:
channel = RolloutChannel.parse(value, strict=True)
except RolloutConfigurationError:
channel = RolloutChannel.STABLE # explicit fallback with logging Prevention
- Restrict the channel field in user-facing config to the documented names.
- Decide explicitly whether unknown channels are fatal (strict) or fall back to stable.
- Keep the alias list in sync when upgrading headroom — new channels may appear.
When it happens
Trigger: Calling RolloutChannel.parse('prod', strict=True), parse('staging', strict=True), or parsing a snapshot whose 'channel' field is garbage; non-strict calls never raise — they warn and return STABLE.
Common situations: Abbreviations like 'prod' or 'staging' not in the alias table; a renamed channel in a newer version deserializing an older snapshot; free-text channel fields from user config.
Related errors
- bedrock_eventstream_parse_failed
- Unknown provider: {self.llm_config.provider}
- HEADROOM_LEARN_CLI={cli_override!r} is not a supported CLI.
- max_size must be at least 1, got {max_size}
- save_path must be provided when auto_save is True
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/f452f5809796f8a5.
Report an issue: GitHub.