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
- Define the table in a loaded layer: `[model_providers.my-proxy]` with `name`, `base_url`, and `env_key` (plus `wire_api` if needed).
- Fix the id so it exactly matches the table name or a built-in provider id.
- For `ollama_chat`, follow the migration described in the removal message to the current Ollama provider.
- 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
- Define [model_providers.<id>] in the same layer that sets model_provider
- Keep provider ids exact; they are case-sensitive table names
- Run codex configs through schema validation in CI
- When deleting a provider table, grep for lingering model_provider references
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
- No MCP server named '{name}' found.
- Environment variable {env_var} for MCP server '{server_name}
- Invalid MCP server name '{server_name}': must match pattern
- executor-owned MCP server `{server_name}` cannot use hosted
- MCP server '{server}' is not registered by the hosted runtim
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/03d63848355b8236.
Report an issue: GitHub.