Skip to content

A local branch named t3code makes every worktree thread fail with an opaque "git worktree add failed" #16163

Description

@sam-goodwin

What happened

Every new worktree thread in one project failed immediately with:

Workspace preparation failed during provision worktree: Git command failed in GitVcsDriver.createWorktree (~/workspaces/<repo>): git worktree add failed

Four thread launches in a row failed the same way. The message gave no hint of the cause.

Diagnosis

The repository had a local branch named exactly t3code. New worktree threads are provisioned under a temporary branch t3code/<8 hex> (WORKTREE_BRANCH_PREFIX in packages/shared/src/git.ts, used by buildTemporaryWorktreeBranchName, called from ThreadLaunchService.ts in the provision-worktree step). Git stores refs hierarchically, so once refs/heads/t3code exists as a plain ref, no refs/heads/t3code/* ref can be created. git worktree add -b t3code/<hex> ... dies in ~15 ms with:

fatal: 'refs/heads/t3code' exists; cannot create 'refs/heads/t3code/<hex>'

Two things compound this:

  1. The temporary branch name is generated without checking whether the t3code/ namespace is usable, and there is no fallback name, so every worktree thread in that repo fails until the user discovers and renames the branch by hand.
  2. executeGit in apps/server/src/vcs/GitVcsDriverCore.ts records only stderrLength and replaces the detail with the static fallbackErrorDetail ("git worktree add failed"), so git's one-line explanation never reaches the UI, the trace, or the DB. This is Git command errors discard stderr, making failures opaque to callers #4380. The span GitVcsDriver.createWorktree is even recorded as Success because the executor runs with allowNonZeroExit: true; only the parent createWorktree span carries the failure.

The repo itself was healthy: a manual git worktree add with any other branch name worked, and after deleting the t3code branch the exact command the app runs succeeds.

A user having a branch named t3code is not far-fetched: anyone who has worked on T3 Code integration or named a scratch branch after the tool will hit this.

Steps to reproduce

  1. In any git repo registered as a T3 Code project, run git branch t3code (no need to check it out).
  2. Open the project in T3 Code with the default thread environment mode set to worktree.
  3. Send a message to start a new thread.

Expected: the worktree is created, or the error names the conflicting ref.
Actual: the thread fails during provision-worktree with "git worktree add failed" and no further detail.

Delete the branch and retry: it works.

Version

Desktop Nightly 0.0.46-nightly.20261005.2689 (3e6b450), which matches main at the time of filing. npx t3 triage reported CLI 0.0.45.

Environment

macOS 25.5.0 (arm64), Node v26.8.2, git 2.50.1 (Apple Git-155). Desktop app connected to its local server on 127.0.0.1:3773. Provider: grok.

Evidence

# server.trace.ndjson (home path redacted)
{"type":"effect-span","name":"GitVcsDriver.createWorktree","durationMs":16.899417,"attributes":{"git.operation":"GitVcsDriver.createWorktree","git.cwd":"~/workspaces/<repo>","git.args_count":8},"exit":{"_tag":"Success"}}
{"type":"effect-span","name":"createWorktree","durationMs":26.521959,"exit":{"_tag":"Failure","cause":"GitCommandError: Git command failed in GitVcsDriver.createWorktree (~/workspaces/<repo>): git worktree add failed\n    at .../apps/server/dist/binCli-La0WuPPZ.mjs:77966:98\n    at createWorktree (.../binCli-La0WuPPZ.mjs:79848:75)\n    at GitManager.createWorktree (.../binCli-La0WuPPZ.mjs:214341:128)\n    at ThreadLaunchService.prepareInBackground (Nightly)\n    at ThreadLaunchService.launch (Nightly)"}}
{"type":"effect-span","name":"ThreadLaunchService.prepareInBackground","durationMs":1184.388375,"exit":{"_tag":"Failure","cause":"ThreadLaunchError: Thread launch <command-id> failed during provision-worktree. ..."}}

# run record in statev2.sqlite
"workspacePreparation":{"type":"worktree","baseRef":"main","startFromOrigin":true}  status: failed

# repo state
$ git show-ref refs/heads/t3code
4eae83e93eadeb6873c4428811b2cefb9cd6477d refs/heads/t3code

# exact command shape the app runs, re-run by hand
$ GIT_PROGRESS_DELAY=0 LC_ALL=C git -c checkout.workers=0 worktree add -b t3code/17f27745 ~/.t3/worktrees/<repo>/t3code-17f27745 <origin/main sha>
Preparing worktree (new branch 't3code/17f27745')
fatal: 'refs/heads/t3code' exists; cannot create 'refs/heads/t3code/17f27745'
exit=255

# after `git branch -d t3code`
$ ... worktree add -b t3code/35c649bf ...
Preparing worktree (new branch 't3code/35c649bf')
Updating files: 100% (19600/19600), done.
exit=0

Related issues

Fix applied or workaround

The t3code branch was fully merged into main, had no upstream, and was not checked out anywhere, so it was deleted with git branch -d t3code. New threads in the project provision normally afterwards. Renaming it (git branch -m t3code t3code-local) works just as well.

Possible app-side fixes: check git check-ref-format/show-ref for the prefix before generating the temp name and fall back to a sibling namespace (for example t3code-<hex>), and/or surface a capped stderr excerpt in GitCommandError (#4380).

Filed by

claude (fable-5.1) via t3 triage, Claude Code

Activity

  1. juliusmarminge commented on Oct 5, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Triage

    Thanks for the clear repro and the root-cause notes, @sam-goodwin! This reproduces on main at 3e6b45028c, the nightly it was filed against.

    What I found

    • A local branch named exactly t3code occupies refs/heads/t3code, so Git refuses every refs/heads/t3code/<hex> ref. Default worktree launches always use that shape, and nothing checks whether the namespace is free.
    • buildTemporaryWorktreeBranchName in packages/shared/src/git.ts returns t3code/<8 hex>. ThreadLaunchService uses it whenever a worktree launch has no explicit branch, and the mobile client sends the same shape as worktreeBranchName. git worktree add -b then fails in GitVcsDriver.createWorktree. Retrying doesn't help, because every temporary name lands in the same blocked namespace. Renaming or deleting the t3code branch is the workaround for now.
    • This is separate from Use repository-derived worktree branch names instead of the hardcoded t3code prefix #272. The t3code/ prefix marks branches T3 Code created, and the collision happens before the background rename to the final branch name. Any fallback name would still need to match isTemporaryWorktreeBranch, since that matcher enables the background rename and lets the web client ignore stale temporary refs. A plain t3code-<hex> name would skip the rename and stick.
    • The opaque git worktree add failed text is Git command errors discard stderr, making failures opaque to callers #4380: executeGit keeps only stderrLength and substitutes fallbackErrorDetail. Fixing that would make this self-diagnosable, but wouldn't stop the launch failure.

    Likely fix area

    • Check whether refs/heads/t3code exists before picking the temporary name, and fall back to a name that isTemporaryWorktreeBranch still recognizes.
    • Or detect this specific Git error and show a targeted message telling the user to rename the conflicting branch.

    A maintainer will decide on the fix direction.

  2. added
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 5, 2026
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.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions