headroomlabs-ai/headroom · error · ValueError
{token!r} not one of {list(field.choices)}
Error message
{token!r} not one of {list(field.choices)} What it means
ValueError from _coerce in headroom/settings_store.py when an 'enum' field receives a value whose string form is not in the field's declared choices (line 794). The message lists the accepted choices. Note the value is coerced with str(), so numbers are compared by their string form. Reported per-field via SettingsValidationError.field_errors.
Source
Thrown at headroom/settings_store.py:794
raise ValueError(f"expected a number, got {value!r}")
number: int | float
if field.type == "int":
if isinstance(value, float) and not value.is_integer():
raise ValueError(f"expected an integer, got {value!r}")
number = int(value)
else:
number = float(value)
if not math.isfinite(number):
raise ValueError(f"expected a finite number, got {value!r}")
if field.minimum is not None and number < field.minimum:
raise ValueError(f"must be >= {field.minimum}")
if field.maximum is not None and number > field.maximum:
raise ValueError(f"must be <= {field.maximum}")
return number
if field.type == "enum":
token = str(value)
if token not in field.choices:
raise ValueError(f"{token!r} not one of {list(field.choices)}")
return token
if field.type == "csv-list":
tokens = value if isinstance(value, list | tuple) else str(value).split(",")
tokens = [str(token).strip() for token in tokens]
tokens = [token for token in tokens if token]
return ",".join(tokens) if tokens else None
if field.type == "header-map":
if isinstance(value, dict):
parsed = value
else:
try:
parsed = json.loads(str(value))
except (ValueError, TypeError) as exc:
raise ValueError("expected a JSON object of header name/value strings") from exc
if not isinstance(parsed, dict) or not all(
isinstance(k, str) and isinstance(v, str) for k, v in parsed.items()
):
raise ValueError("expected a JSON object of header name/value strings")View on GitHub (pinned to 322425c43b)
Solutions
- Use one of the exact choices listed in the error message (match case exactly).
- If the value comes from user input, present the choices from the field metadata instead of a free-text box.
- After upgrading headroom, re-check enum choices for renamed values.
Example fix
# before
save({'mode': 'Cache'}) # ValueError: 'Cache' not one of ['cache', 'token']
# after
save({'mode': 'cache'}) Defensive patterns
Strategy: validation
Validate before calling
from headroom.settings_store import _BY_KEY
def valid_choice(key: str, v) -> bool:
f = _BY_KEY.get(key)
return f is None or str(v) in f.choices Type guard
def is_valid_enum(key: str, v: str) -> bool:
f = _BY_KEY.get(key)
return f is not None and str(v) in f.choices Try / catch
except SettingsValidationError as e:
for key, msg in e.field_errors.items():
if 'not one of' in msg:
choices = _BY_KEY[key].choices
payload[key] = next((c for c in choices if c.lower() == str(payload[key]).lower().strip()), payload[key])
store.save(payload) Prevention
- Build dropdowns from field.choices, never free text.
- Lowercase-and-strip user input before matching enum choices.
When it happens
Trigger: save({'proxy_mode': 'Cache'}) when choices are lowercase; passing a mode value from an older headroom version whose name was renamed; trailing whitespace or a copy-pasted synonym like 'cached'/'fast'.
Common situations: Case mismatches from hand-edited env vars; enum values renamed between releases; synonyms typed from memory instead of copied from docs.
Related errors
- Invalid memory_mode={config.memory_mode!r}; expected one of
- Invalid memory_storage_mode={config.memory_storage_mode!r};
- unknown rollout channel {value!r}
- expected a boolean, got {value!r}
- expected a number, got {value!r}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/86fa42eaadee99b4.
Report an issue: GitHub.