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 None

View on GitHub (pinned to 322425c43b)

Solutions

  1. Pick ONE spelling per field — prefer the canonical JSON/API key — and delete the env-alias duplicate.
  2. If both must coexist temporarily, make the values literally identical (equal duplicates are accepted).
  3. 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

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


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/9f8f31ab79d8bc48. Report an issue: GitHub.