Skip to content

[Bug]: Mobile: a model pick that was already delivered moves the thread back on a later message #24564

Open

Description

@BelugaCrypto

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/mobile

Steps to reproduce

  1. On the mobile app, open a thread running on model B.
  2. Pick model A in the composer and send. Lock the phone right away, before the app receives the thread update showing the thread on model A.
  3. On desktop or web, switch the thread to model C and send a message.
  4. Unlock the phone, type a follow-up without touching the model picker, and send it.

Expected behavior

The follow-up runs on model C, the thread's current model. A pick should apply to the message it was sent with, not to later ordinary messages.

Actual behavior

The follow-up carries model A, and the server switches the thread back to A with a context handoff.

Cause: the composer keeps a pick in the draft until the app sees the thread on that exact model (subscribeComposerDraftModelReconciliation in apps/mobile/src/state/use-composer-drafts.ts). An app that slept through that moment, while another client moved the thread, never sees it, so the pick stays and rides along with the next message. The client can't release the pick from the shell alone: a pick is applied to the thread only when its run starts, and the shell doesn't say whether a run is still waiting (held behind a failed run, a Stop, or a reordered queue).

Impact

Minor bug or occasional failure

Version or commit

main @ eea9895

Environment

iOS app 2.0.0 with a self-hosted server; source behaviour unchanged on main @ eea9895

Logs or stack traces

Screenshots, recordings, or supporting files

No response

Workaround

No response

Activity

  1. added
    bugSomething is broken or behaving incorrectly.
    needs-triageIssue needs maintainer review and initial categorization.
    on Oct 24, 2026
  2. vitalyiegorov commented on Oct 26, 2026

    @vitalyiegorov
    Contributor

    I hit this too: 4 machines, several provider accounts, iOS app. I had picked a model on the phone for a thread earlier. Later I continued the thread on another machine, then sent a follow-up from the phone without touching the picker. The thread switched back to my old pick with a context handoff.

    Why the client can't release the pick safely today: the server fixes each queued message's model when the message arrives (command.modelSelection ?? projection.thread.modelSelection in Orchestrator.ts). thread.modelSelection changes only when a run starts. So if the app released the pick when the message was accepted, a quick follow-up queued behind the picked message would go back to the old model. Keeping the pick until the thread shows it avoids that, but a phone that sleeps through that moment keeps the pick forever.

    Proposed fix (two small parts):

    1. Server: a user message with no model that is queued (not steering) follows the newest queued run's model, not thread.modelSelection. Steering and server-created messages are unchanged.
    2. Mobile: release the draft pick once the outbox delivers a message carrying it. The pick then applies to the message it was sent with, which is the expected behaviour above.

    This needs #24562 (follow-ups carry a model only when picked); otherwise unpicked follow-ups still send the cached model. I have this working on top of #24562 with a server integration test (an unpicked follow-up queued behind a Claude pick runs on Claude) and a mobile draft test. Happy to open it as a PR if the direction looks right.

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

    bugSomething is broken or behaving incorrectly.needs-triageIssue needs maintainer review and initial categorization.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions