Skip to content

[Bug]: Worktree creation fails at configureBaseRef when .git/config is locked and leaves an orphan worktree + branch #11735

Description

@erannave

Steps to reproduce

Deterministic, without any AI provider involved:

  1. Open any git repository as a T3 Code project (WSL runtime).
  2. On the host, simulate a held config lock: touch <repo>/.git/config.lock (any pre-existing file works; git's config writer uses O_CREAT|O_EXCL on that path).
  3. Create a new thread with a worktree.

How it actually happens in practice (no manual touch): Claude Code's Linux/WSL sandbox deny-writes <main-repo>/.git/config.lock with a bubblewrap bind mount and materializes a 0-byte, mode 0444 placeholder on the host for the duration of every sandboxed Bash command, in the main repo's .git even when the thread runs in a linked worktree (anthropics/claude-code#78818, confirmed by a maintainer). Any T3 worktree creation that overlaps a Bash command in another thread hits step 2 for free, and the provider chosen for the new thread is irrelevant: my last failure was a Codex thread, created while a Claude thread in another worktree was 5 minutes into a 7-minute test run. With three busy threads I got 7 failures in one afternoon.

Expected behavior

Either of:

  • createWorktree treats git config branch.<new>.gh-merge-base <base> as best-effort: log a warning, keep the worktree, let the thread start (the merge base can be re-derived later, resolveBaseBranchForNoUpstream already falls back to the default branch).
  • Or, if the config write is required, roll back the git worktree add and the branch so no orphan is left behind, and retry the config write a few times (the lock is transient by nature).

Also: surface git's stderr in the error (#4380). "Git command exited with a non-zero status." hid a one-line could not lock config file .git/config: File exists that would have made the diagnosis trivial.

Actual behavior

GitVcsDriver.createWorktree runs git worktree add -b <new> <path> <ref> (succeeds), then git config branch.<new>.gh-merge-base <base> in the main repo, which exits 255. The whole command fails with:

Git command failed in GitVcsDriver.createWorktree.configureBaseRef (/home/eran/batalyse/batalyse): Git command exited with a non-zero status.

The thread is never created, but the worktree directory under ~/.t3/worktrees/<repo>/t3code-<id> and the branch t3code/<id> remain. I had to clean up 4 orphans by hand (git worktree remove + git branch -D); nothing in the UI shows them.

How bad is this in practice?

Major degradation or frequent failure

Version or commit

T3 Code (Alpha) 0.0.40, WSL runtime sha256-02c38816d0b6722af4ec74c48982ab009586fe7f84274cc757fe8f039c4784db

Environment

Windows 11 desktop app, WSL2 Ubuntu (kernel 6.18.33.2-microsoft-standard-WSL2), git 2.53.0, Claude Code 2.1.270 as provider with the sandbox enabled

Logs or stack traces

{"type":"effect-span","name":"createWorktree","durationMs":1241.5,"exit":{"_tag":"Failure","cause":"GitCommandError: Git command failed in GitVcsDriver.createWorktree.configureBaseRef (/home/eran/batalyse/batalyse): Git command exited with a non-zero status.\n    at createWorktree (file:///home/eran/.t3/wsl-runtime/sha256-02c38816.../apps/server/dist/bin.mjs:83455:66)\n    at createWorktree (definition) (file:///home/eran/.t3/wsl-runtime/sha256-02c38816.../apps/server/dist/bin.mjs:83128:25)"}}
{"type":"effect-span","name":"GitVcsDriver.createWorktree","durationMs":1216.7,"attributes":{"git.operation":"GitVcsDriver.createWorktree","git.cwd":"/home/eran/batalyse/batalyse","git.args_count":6},"exit":{"_tag":"Success"}}
{"type":"effect-span","name":"GitVcsDriver.createWorktree.configureBaseRef","durationMs":10.8,"attributes":{"git.operation":"GitVcsDriver.createWorktree.configureBaseRef","git.cwd":"/home/eran/batalyse/batalyse","git.args_count":3},"exit":{"_tag":"Success"}}

(The last span reads Success because executeGit runs with allowNonZeroExit: true and checks the exit code outside the span, so the trace never records the failing exit code or stderr.)

Reproduced by hand on the host while the placeholder existed:

$ git config branch.zz-probe.gh-merge-base main; echo exit=$?
error: could not lock config file .git/config: File exists
exit=255
$ ls -la .git/config.lock
-r--r--r-- 1 eran eran 0 Sep 14 13:21 .git/config.lock

Workaround

Delete the stale <repo>/.git/config.lock when it is a 0-byte 0444 file (a bubblewrap placeholder, not a git lock), create the worktree while no other thread is running a Bash command, and remove orphans with git worktree remove <path> && git branch -D t3code/<id>.

Activity

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

    acceptedfeature request acceptedbugSomething 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