Skip to content

[Bug]: Worktree launch with an explicit branch name fails opaquely when a branch already owns its prefix (e.g. werkstatt vs werkstatt/baseline) #29297

Closed

Description

@moyn-enno

Before submitting

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

Area

Server: thread launch / worktree provisioning (create_threads, t3_thread_launch)

What happened

An agent launched a new worktree thread through the T3 MCP and chose the branch name werkstatt/baseline. The repo already had a local branch named werkstatt. The thread failed at once:

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

Git stores refs as paths. When refs/heads/werkstatt exists, no refs/heads/werkstatt/* ref can be made. The reverse also fails: when werkstatt/x exists, you cannot create werkstatt. git check-ref-format --branch accepts both names, so the conflict only shows up when the ref is written.

This is the same bug as #16163, but for names the caller picks. #16167 fixed only the built-in temporary prefix. ThreadLaunchService checks refs/heads/${WORKTREE_BRANCH_PREFIX} and flattens the name, but only when isTemporaryWorktreeBranch(branch) is true. An explicit branch name from an agent, the MCP tools, or the UI goes to createWorktree unchecked.

There is a second, smaller problem. createWorktree runs createBranchAt(..., "git worktree add failed") through executeGitWithStableDiagnostics. The fallback detail replaces git's stderr, and no failure class matches a ref-namespace conflict. So the UI says git worktree add failed for a git branch call and drops git's one-line cause ('refs/heads/werkstatt' exists; cannot create 'refs/heads/werkstatt/baseline'). The agent that made the call cannot see why it failed or how to fix it.

Steps to reproduce

Plain git (git 2.47.3):

d=$(mktemp -d) && cd "$d"
git init -q -b main && git commit -q --allow-empty -m init
git branch werkstatt

git check-ref-format --branch werkstatt/baseline   # accepted, exit 0
git branch --no-track -- werkstatt/baseline main   # what createWorktree runs first
# fatal: cannot lock ref 'refs/heads/werkstatt/baseline': 'refs/heads/werkstatt' exists; cannot create 'refs/heads/werkstatt/baseline'

git branch foo/bar && git branch foo               # reverse case
# fatal: cannot lock ref 'refs/heads/foo': 'refs/heads/foo/bar' exists; cannot create 'refs/heads/foo'

git worktree add -q -b werkstatt-baseline ../wt main   # flat sibling works

In T3 Code:

  1. In a repo registered as a project, run git branch werkstatt.
  2. Have an agent call t3_thread_launch (or create_threads) with a worktree strategy, base main, and branch werkstatt/baseline. Starting a worktree thread from the UI with that branch name also works.
  3. The thread fails during provision-worktree with the message above.

Expected behavior

  • T3 checks an explicit branch name for ref-namespace conflicts in both directions before it creates the thread or touches the repo.
  • On a conflict, the tool call returns a clear error to the caller, for example: branch "werkstatt" exists, so "werkstatt/baseline" cannot be created; use e.g. "werkstatt-baseline". The agent can then retry in the same turn, and no failed thread is left behind. Explicit names should not be renamed silently. Only temporary names should flatten, as fix(server): worktree threads survive a local branch named t3code #16167 already does.
  • If git still fails, the error shows git's stderr and names the step that failed (git branch, not git worktree add).

Actual behavior

The thread is created and then fails in provision-worktree with only git worktree add failed. The cause is hidden, so the agent cannot correct the name, and the user has to look at the repo's refs to find out why.

Impact

Agents often pick topic/name branch names. Any repo that has a branch with the same name as the topic (werkstatt, exp, feature, ...) makes every such launch fail with no clue why. Retrying with the same name always fails.

Suggested test case

In the ThreadLaunchService tests, next to the #16167 test for a blocking t3code branch:

  1. A repo with branch werkstatt, and a launch with explicit branch werkstatt/baseline. The launch is rejected before a thread is created, the error names refs/heads/werkstatt, and no branch or worktree is left behind.
  2. A repo with branch werkstatt/x, and a launch with explicit branch werkstatt. Same result as case 1.
  3. A repo with branch werkstatt, and a launch with explicit branch werkstatt-baseline. The launch succeeds, which rules out a check that is too broad.
  4. A GitVcsDriverCore test: when createWorktree hits a ref-namespace conflict, the GitCommandError detail or reason carries git's cause, not the static git worktree add failed.

Version or commit

Desktop 0.1.6 (Linux). The code paths above were checked on main at 47f2c8d (2026-11-02): ThreadLaunchService.ts around the isTemporaryWorktreeBranch check, and GitVcsDriverCore.ts createWorktree / createBranchAt.

Environment

Linux x64, git 2.47.3.

Related: #16163, #16167, #8645, #28354.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions