zylon-ai/private-gpt · error · ValueError

Conflict setting environment variable for model {model_id}:

Error message

Conflict setting environment variable for model {model_id}: {env_key}. Parameter '{key}' is already set as a scalar value.

What it means

Raised by discover_models_from_environment while flattening PGPT_MODELS_* environment variables into nested model config dicts. Double underscores in a parameter name create nested dicts (PGPT_MODELS_CLAUDE_CONFIG__TEMPERATURE -> {'config': {'temperature': ...}}). If one variable already set an intermediate path segment to a scalar string and a later variable tries to descend through that same segment as a dict, the scalar blocks dictionary creation and this ValueError fires.

Source

Thrown at private_gpt/settings/settings_loader.py:127

        - Each model automatically gets a "name" field with its ID
    """
    models = {}

    def _set_nested_param(
        config: dict[str, Any],
        param_keys: list[str],
        value: str,
        model_id: str,
        env_key: str,
    ) -> None:
        """Set a nested parameter value, creating intermediate dictionaries."""
        current = config

        for key in param_keys[:-1]:
            if key not in current:
                current[key] = {}
            elif not isinstance(current[key], dict):
                raise ValueError(
                    f"Conflict setting environment variable for model {model_id}: {env_key}. "
                    f"Parameter '{key}' is already set as a scalar value."
                )
            current = current[key]

        current[param_keys[-1]] = value

    for key, value in environ.items():
        if key.startswith("PGPT_MODELS_") and key.count("_") >= 3:
            _, _, model_id, param = key.split("_", 3)

            model_id = model_id.lower()
            if model_id not in models:
                models[model_id] = {"name": model_id}

            param_lower = param.lower()
            param_keys = param_lower.split("__")

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Rename the scalar variable so it is not also used as a nested prefix (e.g. PGPT_MODELS_GPT4_OPTIONS_LABEL=x instead of PGPT_MODELS_GPT4_OPTIONS=x)
  2. Or convert the scalar into a nested value: replace PGPT_MODELS_GPT4_CONFIG=abc with PGPT_MODELS_GPT4_CONFIG__VALUE=abc
  3. List all colliding vars: env | grep '^PGPT_MODELS_' and remove the stale one (often from .env, compose file, or CI secrets)
  4. If both values are genuinely needed, move one into settings.yaml instead of environment discovery

Example fix

# before (conflict: OPTIONS is scalar and also a nesting key)
PGPT_MODELS_GPT4_OPTIONS=low
PGPT_MODELS_GPT4_OPTIONS__TEMPERATURE=0.7

# after
PGPT_MODELS_GPT4_OPTIONS__LEVEL=low
PGPT_MODELS_GPT4_OPTIONS__TEMPERATURE=0.7
Defensive patterns

Strategy: validation

Validate before calling

import os, collections

def find_model_env_conflicts() -> list[str]:
    paths: dict[str, str] = {}  # "model_id.param.path" -> env var
    conflicts: list[str] = []
    for key in os.environ:
        if key.startswith("PGPT_MODELS_") and key.count("_") >= 3:
            _, _, mid, param = key.split("_", 3)
            parts = param.lower().split("__")
            for i in range(1, len(parts)):
                prefix = mid.lower() + "." + ".".join(parts[:i])
                if prefix in paths and paths[prefix] != key:
                    conflicts.append(f"{paths[prefix]} vs {key} ({prefix})")
            full = mid.lower() + "." + ".".join(parts)
            paths.setdefault(full, key)
    return conflicts

Type guard

null

Try / catch

try:
    models = discover_models_from_environment(dict(os.environ))
except ValueError as e:
    # message names the conflicting env key; drop/rename it and retry
    raise SystemExit(str(e)) from e

Prevention

When it happens

Trigger: Defining both PGPT_MODELS_GPT4_CONFIG=abc and PGPT_MODELS_GPT4_CONFIG__TEMPERATURE=0.7 (CONFIG is first a scalar, then needs to be a dict); any pair of PGPT_MODELS_<ID>_<PARAM> variables where one param name is a prefix of another param's double-underscore path, e.g. ..._OPTIONS_X after ..._OPTIONS=y; conflicts inside a .env file loaded into the environment.

Common situations: Incrementally adding tuning env vars to a docker-compose file and accidentally reusing a parameter name as a nesting level; copy-pasting model config from docs that mixes flat and nested styles; a CI environment leaking a stale PGPT_MODELS_* variable that collides with a new one.

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/c4cd645845933b5a. Report an issue: GitHub.