Skip to content

Codex Desktop needs a supported recovery path when a thread's persisted model provider is unavailable #40314

Open

Description

@hobbescalvin414-tech

What variant of Codex are you using?

Codex Desktop and app-server (observed with app-server 0.147/0.148 behavior).

What feature would you like to see?

Codex Desktop should provide a supported way to continue an existing local thread when the thread's persisted model_provider is no longer present in the current configuration.

A common lifecycle is:

  1. A user starts with the built-in openai provider or another existing provider.
  2. A local provider manager temporarily installs an OpenAI-compatible proxy as [model_providers.proxy] and sets model_provider = "proxy".
  3. Threads are created or resumed through that proxy.
  4. The manager later restores the user's original config.toml exactly. The proxy definition is therefore no longer present.
  5. The local thread remains intact in the rollout JSONL and state_5.sqlite.
  6. Even if Desktop lists all providers (thread/list with modelProviders: []), selecting the thread cannot recover it: Desktop calls thread/resume with the thread's persisted modelProvider (proxy), which is no longer configured.

This is distinct from history discovery. Fixing thread/list visibility alone makes the thread visible but still not usable.

Please provide an official recovery path, for example one of:

  • Desktop detects that the persisted provider is unavailable and offers Open with current provider, with an explicit compatibility warning.
  • thread/resume accepts a provider override that can optionally be persisted as the thread's latest effective provider.
  • A dedicated API such as thread/provider/update atomically updates the canonical rollout metadata and SQLite projection.

The important requirements are:

  • Preserve the same thread ID and history.
  • Do not fork the thread into two independently progressing copies.
  • Do not require users or provider managers to rewrite rollout JSONL and SQLite directly.
  • Keep the default safe for encrypted or provider-specific history: migration should be explicit and may be rejected when compatibility cannot be established.

Additional information

Current behavior and constraints observed in source:

  • thread/list can enumerate all providers with modelProviders: [].
  • thread/resume already has an optional modelProvider parameter, so an external client that knows the thread ID can resume the same ID through a compatible current provider.
  • Desktop selects the persisted thread.modelProvider, so a normal sidebar click cannot use that recovery path.
  • thread/metadata/update does not expose model-provider changes.
  • thread/fork supports a target provider, but creates a second thread ID and produces two potentially divergent conversations.
  • Editing only state_5.sqlite is not safe because rollout JSONL remains the durable source and can rebuild the projection.

Related but distinct issues:

This request is specifically for the case where a thread is known and visible, but its persisted provider definition is unavailable and Desktop has no supported same-thread recovery action.

Activity

  1. added
    enhancementNew feature or request
    appIssues related to the Codex desktop app
    app-serverIssues involving app server protocol or interfaces
    sessionIssues involving session (thread) management, resuming, forking, naming, archiving
    on Aug 24, 2026
  2. github-actions commented on Aug 24, 2026

    @github-actions
    Contributor

    Potential duplicates detected. Please review them and close your issue if it is a duplicate.

    Powered by Codex Action

  3. OriyukiAkari commented on Sep 4, 2026

    @OriyukiAkari

    I tested a related core-side piece of the recovery path described here while investigating #17541.

    Tested implementation:
    OriyukiAkari@926c1d1

    In particular, I verified that the existing thread/resume modelProvider override can continue the same thread ID through a different configured provider, but provider-bound encrypted Reasoning/Compaction history cannot safely be replayed verbatim to that replacement runtime.

    The implementation keeps the rollout JSONL and SQLite projection untouched. Instead, it:

    • tracks the loaded history's provider provenance separately from the newest surviving real turn
    • detects a runtime portability boundary when the effective provider changes
    • removes only non-portable prior encrypted Reasoning/Compaction state before provider requests
    • preserves visible user/assistant/tool history
    • persists the portability state through TurnContextItem so it survives app-server restart
    • falls back to SessionMeta.model_provider for legacy histories where no previous real turn survives reconstruction

    I tested this using an existing Desktop/app-server thread with persisted provider openai, then explicitly resumed the same thread ID with effective provider custom.

    Before the change, continuation failed because encrypted history from the previous runtime was sent to the replacement provider.

    After the change, the same thread ID successfully completed:

    1. the first cross-provider resumed turn
    2. a second turn
    3. another turn after completely restarting app-server and resuming the thread again

    No rollout JSONL or SQLite rewriting was required, and the original encrypted history remained persisted rather than being destructively removed.

    This does not implement the Desktop UX requested by this issue: Desktop still needs a supported action such as "Open with current provider" when the persisted provider is unavailable. The implementation is only a tested core safety mechanism for what happens after such an explicit provider override is chosen.

    I posted the fuller root-cause and validation details in #17541.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appapp-serverIssues involving app server protocol or interfacesenhancementNew feature or requestsessionIssues involving session (thread) management, resuming, forking, naming, archiving

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions