Repository navigation
Description
What happened
The environment default for new threads is "New worktree". Most new threads in one project get a worktree, but a few each day start in the main checkout on main. The user did not select "Local". This has happened since at least 2026-10-01, on every nightly since then.
Diagnosis
The client chooses the workspace mode. The server only follows the thread.create it receives:
- Threads that stayed local were created with
branch: "main",worktreePath: nulland no workspace-preparation step. The server made no worktree for them. - Threads that got a worktree were created with
branch: null, then gotprogress:worktreeandprogress:setupsteps.
On the client, the new-thread path can resolve to local when the environment's settings are not in the client cache:
apps/web/src/hooks/useHandleNewThread.ts(~L84) readsenvironmentServerConfigs.get(environmentId)?.settings ?? DEFAULT_SERVER_SETTINGS. If the config for that environment is not loaded (after a reload, a reconnect or a server update), the defaults are used. In the defaults,defaultThreadEnvModeisnull.resolveDefaultEnvMode(~L142) then readst3.json. If there is not3.json,resolveProjectSettingsfalls back to the built-inlocal.resolveEffectiveEnvMode(apps/web/src/components/BranchToolbar.logic.ts~L171) changes any draft mode that is not"worktree"to"local". The send then uses the checked-out branch (main).- The client keeps one draft per project and reuses it. When the current route is already that draft,
handleNewThreaddoes not calculate the mode again. Thus one bad resolution can stay on the draft for later "New thread" actions.
We did not capture the client's config cache at the time of each bad thread, so step 1 as the trigger is probable but not proven. We excluded two other causes: none of the local threads had a stopped or interrupted run (#23600), and the user did not report clicking "Work locally".
Steps to reproduce
Not reproduced deterministically. Probable path:
- Set the environment default for new threads to "New worktree". Do not add a
t3.json, and do not set a per-project override. - Reload the web client, or let it reconnect to the server, and start a new thread in a git project at once (before the environment's server config arrives).
- Send the first message. The thread starts in the main checkout on the current branch, with no worktree.
Version
0.1.2-nightly.20261022.3512 (server and served web client). The same behavior also happened on 0.1.1-nightly.20261018.3335 and 0.1.2-nightly.20261021.3457.
Environment
- Linux x64 (Fedora, kernel 7.2), Node 26.12.1
- Server runs as the background service (
t3 serve) on a cloud VM - Client: web app (
creationSource: "web") connected to that server - Agent: Claude Code 2.1.302
Evidence
Local threads per day vs worktree threads per day in the project (from statev2.sqlite):
2026-10-14 local 7 worktree 10
2026-10-21 local 2 worktree 16
2026-10-22 local 3 worktree 5
thread.created payload of a local thread (excerpt): "branch":"main","worktreePath":null. After that, there were no progress:worktree events.
thread.created payload of a worktree thread (excerpt): "branch":null,"worktreePath":null, then …:progress:worktree, …:progress:setup, and the worktree path was set.
settings.json: "defaultThreadEnvMode": "worktree", "projectSettingsFolded": true, and no defaultThreadEnvMode in projectSettingsOverrides for the project.
Related issues
- fix(web): Cmd+Shift+N stalls while the selected remote computer is reconnecting #10548:
chat.newLocalstalls while a remote computer reconnects. That issue is about the same new-thread path waiting on remote state, but its symptom is a stall, not a wrong mode. - Stopping a thread during "Preparing worktree" makes the next message run in the main project checkout #23600: a stop during "Preparing worktree" makes the next message run in the main checkout. It has the same symptom but a different cause: none of these threads had a stopped run.
- [Bug]:
t3_project_updatesaves scripts and project defaults that are ignored once project settings are folded #14991: project defaults written throught3_project_updateare ignored after the fold. We saw this too: a project-leveldefaultThreadEnvMode: "worktree"had no effect. - [Bug]: New threads in the same project do not preserve the last-used model and working-mode settings #6508: new threads do not keep the last-used composer settings. Related, but it is about model and modes, not the workspace mode.
Fix applied or workaround
Added an untracked t3.json with {"defaultThreadEnvMode": "worktree"} at the repository root (excluded with .git/info/exclude). resolveDefaultEnvMode reads it when the settings resolve to null. Not verified yet, because the race cannot be triggered on purpose.
Suggested fix: do not resolve a new thread's workspace mode from DEFAULT_SERVER_SETTINGS when the environment config is not loaded. Wait for the config, or keep the mode unresolved until send time.
Filed by
Claude Code (Claude Opus 5.5), through t3 triage.
Activity
juliusmarminge commentedon Nov 12, 2026
I tried to reproduce this on the current build and could not.
Commit bfec275 (origin/main). Unit level: added a case to apps/web/src/hooks/useHandleNewThread.test.ts (new and reusable draft variants) where the environment's setting is defaultThreadEnvMode "worktree" but its server config is missing from the client cache; both fail on main (persisted envMode is ["local"] for the new draft and ["local","local"] for the reused draft), the other 10 tests pass. Live: ran
T3CODE_DEV_SEED=0 vp run dev, paired the web client in the preview browser, set defaultThreadEnvMode "worktree" in the dev settings.json, added a fresh git repo with no t3.json as a project. (1) New thread in it showed "New worktree". (2) Cleared the IndexedDBserver-configstore, reloaded and clicked "New thread in repo" as soon as it rendered: still "New worktree" (the UI became usable only ~6 s after load, once config had arrived). (3) Cleared the cache again, paused the dev server process (SIGSTOP, PID owning the server port, cwd verified) and reloaded: the page stayed blank waiting on /api/auth/session, so the project list never rendered without config; after SIGCONT it came back as "New worktree". The race could not be triggered naturally with a single local environment; the reporter's remote web client reconnecting to a cloud server is the likely trigger.Closing as not planned. If it still happens for you, reply with the exact steps and the version you are on and it will be looked at again.