Skip to content

Switching models mid-session does not update provider/endpoint — Ollama endpoint persists after switching to gpt-5.4 #18764

@KhryptorGraphics

Description

@KhryptorGraphics

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

  1. Launch codex --model glm-5.1:cloud --local-provider ollama
  2. Confirm it works (requests hit localhost:11434)
  3. Switch model to gpt-5.4 via the model picker
  4. Send a prompt — requests still go to localhost:11434 and 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:

  1. Startup: Config::from_config() resolves model_provider_id (e.g. "ollama") and looks up the corresponding ModelProviderInfo from model_providers map, which has base_url: Some("http://localhost:11434/v1"). This gets stored in SessionConfiguration.provider.

  2. Model switch: When the user picks a new model, the TUI sends Op::OverrideTurnContext { model: Some("gpt-5.4"), ... }. The handler converts this into a CollaborationMode update and calls SessionConfiguration.apply(&updates).

  3. SessionConfiguration.apply() (codex-rs/core/src/session/session.rs:110) updates collaboration_mode (which holds the model name) but never touches provider. The provider: ModelProviderInfo field stays set to Ollama.

  4. New turn creation: new_turn_from_configuration() passes session_configuration.provider.clone() to make_turn_context(), which creates a ModelProvider from the stale Ollama provider info.

  5. TurnContext.with_model() (codex-rs/core/src/session/turn_context.rs:97) similarly clones self.provider without 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 openai provider
  • 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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcustom-modelIssues related to custom model providers (including local models)sessionIssues involving session (thread) management, resuming, forking, naming, archiving

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions