headroomlabs-ai/headroom · error · SettingsValidationError
conflicting values supplied for {source_keys[key]!r} and {in
Error message
conflicting values supplied for {source_keys[key]!r} and {incoming_key!r} What it means
Raised as SettingsValidationError from _normalize_values in headroom/settings_store.py when the same logical setting is supplied twice through two different keys — typically its environment-variable alias (e.g. OPENAI_TARGET_API_HEADERS) and its JSON/API key (openai_extra_headers) — with values that differ. The message names both the first-seen source key and the conflicting incoming key. Equal duplicate values are fine; only mismatched values conflict.
Source
Thrown at headroom/settings_store.py:750
def _normalize_values(values: dict[str, Any]) -> dict[str, Any]:
"""Rewrite known env aliases to their JSON/API keys."""
normalized: dict[str, Any] = {}
source_keys: dict[str, str] = {}
conflicts: dict[str, str] = {}
for incoming_key, value in values.items():
field = _BY_ENV.get(incoming_key)
key = field.key if field is not None else incoming_key
if key in normalized:
if normalized[key] != value:
conflicts[key] = (
f"conflicting values supplied for {source_keys[key]!r} and {incoming_key!r}"
)
continue
normalized[key] = value
source_keys[key] = incoming_key
if conflicts:
raise SettingsValidationError([], conflicts)
return normalized
def _coerce(field: SettingField, value: Any) -> Any:
"""Coerce a raw JSON/env value to the field's Python type.
Returns ``None`` for null and empty values (empty coerces to ``None`` for
every type except a plain ``bool``, which becomes ``False``). Raises
``ValueError`` on bad input so callers can surface a per-field message.
"""
if value is None:
return None
if field.type in ("bool", "optional-bool"):
if isinstance(value, bool):
return value
token = str(value).strip().lower()
if field.type == "optional-bool" and token == "":
return NoneView on GitHub (pinned to 322425c43b)
Solutions
- Pick ONE spelling per field — prefer the canonical JSON/API key — and delete the env-alias duplicate.
- If both must coexist temporarily, make the values literally identical (equal duplicates are accepted).
- Re-run the save; if it still conflicts, inspect the offending keys named in the message and align them.
Example fix
# before
values = {'HEADROOM_PROXY_MODE': 'cache', 'proxy_mode': 'token'}
save(values) # SettingsValidationError: conflicting values
# after
values = {'proxy_mode': 'token'}
save(values) Defensive patterns
Strategy: validation
Validate before calling
from headroom.settings_store import _BY_ENV # env alias -> SettingField
def has_alias_conflicts(values: dict) -> dict[str, str]:
seen = {}
for k, v in values.items():
canon = _BY_ENV[k].key if k in _BY_ENV else k
if canon in seen and seen[canon] != v:
return {canon: f'{canon} supplied twice with different values'}
seen[canon] = v
return {} Try / catch
from headroom.settings_store import SettingsValidationError
try:
store.save(payload)
except SettingsValidationError as e:
# e.field_errors maps the canonical key -> conflict message
for key, msg in e.field_errors.items():
print(f'{key}: {msg}') # drop one of the two spellings Prevention
- Never merge env-alias keys and canonical keys into one payload; normalize first.
- Keep settings in one source of truth (the JSON store) and derive env vars from it.
When it happens
Trigger: Saving settings with a payload that contains both the env alias and the canonical key for one field, e.g. {'HEADROOM_PROXY_MODE': 'cache', 'proxy_mode': 'token'}. Also merging a dotenv file (env-style keys) with an API payload (JSON keys) where one side was updated but not the other.
Common situations: Scripts that load .env into a dict and then merge settings fetched from the settings API; migration code that writes canonical keys while legacy env names linger; copy-pasted config blocks that keep both spellings with drifted values.
Related errors
- recommendations IO error at {path}: {source}
- bedrock_eventstream_parse_failed
- bedrock_eventstream_crc_mismatch
- Error: {e}
- {_WRAP_PROXY_TIMEOUT_ENV} must be a positive integer number
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/9f8f31ab79d8bc48.
Report an issue: GitHub.