[Bug]: Composer applies the settings default's options to a thread saved without options#23497
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/web
Steps to reproduce
Split out from #16406, as asked there. #19341 fixed the refused send; this is the part that is still open.
- In Settings → General → New threads, set Model to Claude Opus 5.5 and use its traits picker to choose High effort.
- Create a thread whose model selection has no options. For example, from an agent call
t3_thread_launchwithmodelSelection: { instanceId: "claudeAgent", model: "claude-opus-5-5" }. The server stores the selection as given and opens Claude at the catalog default, Medium. - Open the thread in the web or desktop app. Don't touch the model or trait controls. Send a message.
Expected behavior
The composer shows Medium, the effort the thread runs with. A send with untouched controls keeps Medium.
Actual behavior
The composer shows High and sends effort: high. The server applies it (since #19341, even while background agents run), so the thread switches to High although nobody chose that for it. Before #19341 the same send was refused while background agents ran (#16406).
deriveEffectiveComposerModelState (apps/web/src/composerDraftStore.ts) resolves the model as thread → project, but the options as draft → thread → project. A thread saved without options therefore takes the options of the project or settings default.
Threads created in the composer aren't affected, because a new draft already uses the project default as its thread selection. Mobile resolves draft ?? thread as one selection and isn't affected either.
Impact
Minor bug or occasional failure
Version or commit
main @ 5ffe045931
Environment
Web and desktop clients, Claude provider. First seen on desktop 0.0.46-nightly.20261003.2610 (#16406).
Logs or stack traces
| 1 | # main @ 5ffe045931 with the resolver test from #16546, without its fix |
| 2 | FAIL src/modelSelection.test.ts > instance-scoped model selection > composer model option precedence > does not inherit settings options for an optionless existing thread |
| 3 | + "value": "high", |
| 4 | Tests 1 failed | 29 passed (30) |
Workaround
Pick the effort in the composer before the first send, or have the launching agent pass effort in t3_thread_launch.
Related
- Fix: #16546 makes the options fallback match the model fallback. On main @ 5ffe045931 its test file passes with the fix (30/30) and fails without it, as above.
- #21140 edits the same expression for draft seeds on started threads. It keeps the thread → project options fallback, so it doesn't fix this, and the two PRs will conflict there.
Filed by Claude Opus 5.5 in Claude Code (T3 Code) on behalf of @f4llenz.