Switching models mid-session does not update provider/endpoint — Ollama endpoint persists after switching to gpt-5.4
When launching Codex with an Ollama model (e.g. glm-5.1:cloud via --local-provider ollama), the session correctly uses the Ollama endpoint (http://localhost:11434/v1). However, when switching back to a cloud model like gpt-5.4 mid-session (via /model or model picker), the requests still go to the Ollama endpoint instead of the default OpenAI endpoint (https://api.openai.com/v1). This causes request failures because gpt-5.4 doesn't exist on the Ollama server.
Steps to reproduce
- Launch
codex --model glm-5.1:cloud --local-provider ollama - Confirm it works (requests hit
localhost:11434) - Switch model to
gpt-5.4via the model picker - Send a prompt — requests still go to
localhost:11434and fail
Expected behavior
When switching to a model that isn't available on the current provider, the system should either automatically resolve the correct provider, or at minimum warn the user.
Root cause analysis
The bug is in how OverrideTurnContext handles model switching in the session layer:
- Startup:
Config::from_config()resolvesmodel_provider_id(e.g."ollama") and looks up the correspondingModelProviderInfofrommodel_providersmap, which hasbase_url: Some("http://localhost:11434/v1"). This gets stored inSessionConfiguration.provider.
- Model switch: When the user picks a new model, the TUI sends
Op::OverrideTurnContext { model: Some("gpt-5.4"), ... }. The handler converts this into aCollaborationModeupdate and callsSessionConfiguration.apply(&updates).
SessionConfiguration.apply()(codex-rs/core/src/session/session.rs:110) updatescollaboration_mode(which holds the model name) but never touchesprovider. Theprovider: ModelProviderInfofield stays set to Ollama.
- New turn creation:
new_turn_from_configuration()passessession_configuration.provider.clone()tomake_turn_context(), which creates aModelProviderfrom the stale Ollama provider info.
TurnContext.with_model()(codex-rs/core/src/session/turn_context.rs:97) similarly clonesself.providerwithout resolving a new one.
The OverrideTurnContext protocol message (codex-rs/protocol/src/protocol.rs:505) only carries model: Option<String> — there is no model_provider_id field to communicate a provider change.
Proposed fix
Option A (recommended): Auto-resolve provider on model change
In SessionConfiguration.apply() (or update_settings()), after updating collaboration_mode.model, re-resolve the provider:
- If the model is available in the remote model catalog → switch to the
openaiprovider - If the model slug matches a known OpenAI prefix (gpt-, o1-, o3-, codex-) → switch to
openai - Otherwise → keep the current provider (Ollama/LMStudio)
This requires passing Config.model_providers into SessionConfiguration.apply(), which already has access via original_config_do_not_use.
Option B: Add model_provider_id to OverrideTurnContext
Add a model_provider_id: Option<String> field to the protocol message so the TUI can explicitly specify which provider to use when switching models. This requires the model picker UI to know which provider each model belongs to.
Option C: Resolve in new_turn_from_configuration
In Session::new_turn_from_configuration(), after resolving model_info, check if the current provider is appropriate for the model and switch if needed.
---
Related issues: #15219 (thread/resume doesn't restore model_provider), #17541 (model switch fails with encrypted content error), #17261 (feat: /model support for LM Studio and Ollama), #8319 (/model support for ollama/lmstudio)
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗