headroomlabs-ai/headroom · error · RolloutConfigurationError
unknown rollout feature(s) in {source}: {', '.join(unknown)}
Error message
unknown rollout feature(s) in {source}: {', '.join(unknown)}; valid: {valid} What it means
Raised (as RolloutConfigurationError) by _validate_names in headroom/rollout.py when feature names supplied through HEADROOM_FEATURES / HEADROOM_DISABLE_FEATURES environment variables or the requested=/disabled= arguments of resolve_rollout() contain names that are not keys of the FEATURES registry. The message lists the unknown names and the valid set. With strict=True (the snapshot path parses rollout config strictly) it raises; with strict=False it only logs a warning and ignores the unknown names (fail-closed: the feature stays off).
Source
Thrown at headroom/rollout.py:359
elif _falsey(environ[alias]):
legacy_disabled.add(spec.name)
return _resolve_snapshot(
channel=self.channel,
explicit_requested=set(self.config.explicit_requested),
explicit_disabled=set(self.config.explicit_disabled),
legacy_requested=legacy_requested,
legacy_disabled=legacy_disabled,
unsafe=self.unsafe_allow_unstable,
)
def _validate_names(names: set[str], *, source: str, strict: bool) -> frozenset[str]:
unknown = sorted(names - FEATURES.keys())
if unknown:
valid = ", ".join(sorted(FEATURES))
message = f"unknown rollout feature(s) in {source}: {', '.join(unknown)}; valid: {valid}"
if strict:
raise RolloutConfigurationError(message)
logger.warning("%s; ignoring unknown names (fail-closed)", message)
return frozenset(names & FEATURES.keys())
def resolve_rollout(
environ: Mapping[str, str] | None = None,
*,
requested: Iterable[str] = (),
disabled: Iterable[str] = (),
strict: bool = False,
) -> RolloutSnapshot:
"""Resolve all rollout inputs exactly once into an immutable snapshot."""
env = os.environ if environ is None else environ
channel = RolloutChannel.parse(env.get("HEADROOM_ROLLOUT_CHANNEL"), strict=strict)
requested_names = _split_names(env.get("HEADROOM_FEATURES")) | {
normalized for name in requested if (normalized := name.strip().lower().replace("-", "_"))
}View on GitHub (pinned to 322425c43b)
Solutions
- Compare the offending names against the valid list in the error message and fix typos/dashes-vs-underscores.
- If the feature disappeared, remove it from HEADROOM_FEATURES / HEADROOM_DISABLE_FEATURES or the requested=/disabled= arguments after checking `headroom` docs or FEATURES keys for the current name.
- Pin or upgrade to a headroom version whose FEATURES registry contains the names you use.
- If you intentionally pass untrusted/user-supplied names, call resolve_rollout(..., strict=False) so unknown names are ignored with a warning instead of raising.
Example fix
# before HEADROOM_FEATURES=conetxt_packing # typo, raises RolloutConfigurationError # after HEADROOM_FEATURES=context_packing
Defensive patterns
Strategy: validation
Validate before calling
from headroom.rollout import FEATURES, resolve_rollout
names = ['context_packing', 'my_flag']
unknown = [n for n in names if n not in FEATURES]
if unknown:
raise SystemConfigError(f'unknown features: {unknown}')
snap = resolve_rollout(requested=names) Type guard
from headroom.rollout import FEATURES
def is_known_feature(name: str) -> bool:
return name in FEATURES Try / catch
from headroom.rollout import RolloutConfigurationError
try:
snap = resolve_rollout(requested=names, strict=True)
except RolloutConfigurationError as e:
# message already lists valid names; drop unknowns and retry or fail loudly
raise Prevention
- Print sorted(FEATURES) once in CI to keep env var lists in sync.
- Treat unknown feature names in strict mode as a config-drift signal, not something to catch-and-ignore.
When it happens
Trigger: Calling resolve_rollout(requested=['feature_that_does_not_exist']) or setting HEADROOM_FEATURES=nonexistent_flag, or a typo like HEADROOM_FEATURES=conetxt_packing where the registry key is 'context_packing'. The snapshot/strict path (line ~304) always uses strict=True, so any persisted rollout config containing a removed or misspelled feature name raises on load.
Common situations: Feature was renamed or removed in a newer headroom version while a stale env var or saved rollout config still names it; CI pipelines that pin HEADROOM_FEATURES from an old runbook; typos in dotenv files.
Related errors
- unknown rollout channel {value!r}
- recommendations IO error at {path}: {source}
- bedrock_eventstream_parse_failed
- bedrock_eventstream_crc_mismatch
- Error: {e}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/077387a06409bdef.
Report an issue: GitHub.