openai/codex · error · std::io::Error

Model provider `{model_provider_id}` not found

Error message

Model provider `{model_provider_id}` not found

What it means

Config resolves the active provider id (a model_provider override, else cfg.model_provider, else "openai") and looks it up in the provider map built from built_in_model_providers() merged with `[model_providers]` tables across layers. An unknown id returns ErrorKind::NotFound with `Model provider` <id> `not found`. The removed legacy id `ollama_chat` instead produces a dedicated removal message explaining the current Ollama setup.

Source

Thrown at codex-rs/core/src/config/mod.rs:3700

            .clone()
            .filter(|value| !value.is_empty());

        let model_providers =
            merge_configured_model_providers(built_in_model_providers(openai_base_url), cfg.model_providers)
                .map_err(|message| std::io::Error::new(std::io::ErrorKind::InvalidData, message))?;

        let model_provider_id = model_provider
            .or(cfg.model_provider)
            .unwrap_or_else(|| "openai".to_string());
        let model_provider = model_providers
            .get(&model_provider_id)
            .ok_or_else(|| {
                let message = if model_provider_id == LEGACY_OLLAMA_CHAT_PROVIDER_ID {
                    OLLAMA_CHAT_PROVIDER_REMOVED_ERROR.to_string()
                } else {
                    format!("Model provider `{model_provider_id}` not found")
                };
                std::io::Error::new(std::io::ErrorKind::NotFound, message)
            })?
            .clone();

        let shell_environment_policy = cfg.shell_environment_policy.into();
        let allow_login_shell = cfg.allow_login_shell.unwrap_or(true);

        let history = cfg.history.unwrap_or_default();

        if multi_agent_v2.max_concurrent_threads_per_session == 0 {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                "features.multi_agent_v2.max_concurrent_threads_per_session must be at least 1",
            ));
        }
        validate_multi_agent_v2_wait_timeout(
            "features.multi_agent_v2.min_wait_timeout_ms",
            multi_agent_v2.min_wait_timeout_ms,
        )?;

View on GitHub (pinned to 339751715c)

Solutions

  1. Define the table in a loaded layer: `[model_providers.my-proxy]` with `name`, `base_url`, and `env_key` (plus `wire_api` if needed).
  2. Fix the id so it exactly matches the table name or a built-in provider id.
  3. For `ollama_chat`, follow the migration described in the removal message to the current Ollama provider.
  4. Confirm the right CODEX_HOME and profile are active, then retry.

Example fix

# before
model_provider = "my-proxy"

# after
model_provider = "my-proxy"

[model_providers.my-proxy]
name = "My proxy"
base_url = "https://api.example.com/v1"
env_key = "MY_PROXY_API_KEY"
Defensive patterns

Strategy: validation

Validate before calling

# Pre-flight: provider id must be configured or built-in
import tomllib
cfg = tomllib.load(open("config.toml", "rb"))
provider_id = cfg.get("model_provider", "openai")
configured = set(cfg.get("model_providers", {}))
built_ins = {"openai"}  # extend from built_in_model_providers() for your codex version
assert provider_id in configured | built_ins, f"Model provider `{provider_id}` not found"

Try / catch

match config_result {
    Err(ref e) if e.kind() == std::io::ErrorKind::NotFound
        && e.to_string().contains("Model provider") => {
        // list built-in and configured provider ids for the user
    }
    other => other,
}

Prevention

When it happens

Trigger: model_provider = "my-proxy" with no matching `[model_providers.my-proxy]` table; a typo or case mismatch in the id; the table defined in a layer that is not loaded (different CODEX_HOME, inactive profile file); model_provider = "ollama_chat" after that provider's removal.

Common situations: Moving between machines where custom providers live in different config files; renaming or deleting a provider table while model_provider still points at it; forgetting `--profile` so the profile file defining the provider is not loaded; Ollama users upgrading.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/03d63848355b8236. Report an issue: GitHub.