Codex Desktop on Windows hides local history after switching custom OpenAI-compatible providers

Open 💬 2 comments Opened Jul 8, 2026 by QiuYe-123

What version of the Codex App are you using?

  • Codex Desktop package: OpenAI.Codex_26.623.19656.0_x64__2p2nqsd0c76g0
  • App package version: 26.623.19656.0
  • ~/.codex/version.json reports latest_version: 0.141.0

What platform is your computer?

  • Windows
  • Microsoft Windows NT 10.0.26200.0
  • Windows product: Windows 10 Pro for Workstations
  • OS build: 26200

What issue are you seeing?

Codex Desktop hides local chat history after switching between custom OpenAI-compatible model providers.

I have multiple custom providers configured under [model_providers.*] in ~/.codex/config.toml. After changing the active model_provider, the Desktop sidebar and the list_threads tool only show threads for the current provider. Threads created with previous custom providers appear to be missing, but the underlying data still exists and can still be read if the thread id is known.

This is not data deletion. It appears to be a provider-filtering/listing issue.

What steps can reproduce the bug?

  1. Configure multiple custom OpenAI-compatible providers in ~/.codex/config.toml, for example:

```toml
model_provider = provider_a

[model_providers.provider_a]
name = provider_a
base_url = <redacted>
wire_api = responses
requires_openai_auth = true

[model_providers.provider_b]
name = provider_b
base_url = <redacted>
wire_api = responses
requires_openai_auth = true
```

  1. Use Codex Desktop with provider_a and create several chats.
  2. Switch model_provider to provider_b.
  3. Restart or refresh Codex Desktop.
  4. Open the sidebar/history or use the list_threads tool.
  5. Observe that only current-provider chats are shown.
  6. Switch back to the previous provider and observe that the previous-provider history becomes visible again.

What is the expected behavior?

Desktop history views should show all local valid user threads by default, regardless of the currently active model provider.

model_provider should remain metadata on the thread and can be used for resume compatibility warnings, badges, or explicit filtering. It should not hide local history unless the UI explicitly applies a provider filter.

What is the actual behavior?

Only threads matching the current provider are visible in the Desktop/sidebar/thread-listing flow. Threads from other providers appear missing even though they remain present in ~/.codex/state_5.sqlite and under ~/.codex/sessions.

Local evidence

Read-only inspection of ~/.codex/state_5.sqlite shows threads still exist across multiple providers. The exact provider ids are omitted, but the local DB contains several provider buckets. Example counts:

provider bucket 1: 453
provider bucket 2: 338
provider bucket 3: 169
provider bucket 4: 134
provider bucket 5: 118
provider bucket 6: 48
provider bucket 7: 28
provider bucket 8: 6

At the time, list_threads returned only the currently active provider bucket.

However, a non-current-provider thread could still be read directly by id through the app thread API. That confirms the conversation data is still loadable and the problem is in listing/discovery, not storage.

session_index.jsonl also does not contain a provider/model field, so the provider-specific visibility appears to come from the app-server/thread-listing path rather than the raw session index.

Root-cause hint

The generated app-server protocol documents modelProviders as follows:

/**
 * Optional provider filter; when set, only sessions recorded under these
 * providers are returned. When present but empty, includes all providers.
 */
modelProviders?: Array<string> | null

In the installed Windows app.asar, I found 10 occurrences of modelProviders:null in thread-listing paths. The affected bundled files include:

.vite/build/main-CTMsc2Ik.js                         1
.vite/build/src-CoIhwwHr.js                          1
webview/assets/app-window-focus-signal-DcI8YM20.js   1
webview/assets/split-items-into-render-groups-*.js   3
webview/assets/thread-context-inputs-*.js            4

These call sites include recent threads, archived threads, dynamic list_threads, thread-id resolution, background thread hydration, and subagent tree lookup. They appear to be calls that should include all local threads, but they pass modelProviders:null.

Based on the protocol comment, all-provider history calls should pass an empty array instead:

const ALL_MODEL_PROVIDERS: string[] = [];

request(thread/list, {
  ...params,
  modelProviders: ALL_MODEL_PROVIDERS,
});

Related issue

This is related to #20184, but this report is for Windows and custom OpenAI-compatible endpoints, not Azure specifically. I also added supporting evidence there: https://github.com/openai/codex/issues/20184#issuecomment-4918027066

Security notes

  • No API key is included.
  • Custom endpoint URLs are redacted.
  • Local provider ids are anonymized.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗