Repository navigation
Branch switch times out after 10 seconds in large repos and leaves the working tree half-switched #22245
Description
What happened
I switched branches with the branch picker in a large monorepo. The switch failed after about 10 seconds. The old branch was still checked out, but the working tree showed 3,918 deleted files, 2,241 modified files and 50 untracked files from the target branch.
It happened twice. The first time I didn't notice, and my next git pull --autostash stashed the broken tree and then conflicted when applying it back.
Diagnosis
switchRef runs git checkout with a fixed 10-second timeout:
t3code/apps/server/src/vcs/GitVcsDriverCore.ts
Lines 4359 to 4367 in 774c6c1
| // A stale ref must not turn into a path checkout that discards local edits. | |
| yield* executeGitWithStableDiagnostics( | |
| "GitVcsDriver.switchRef.checkout", | |
| input.cwd, | |
| [...checkoutArgs, "--"], | |
| { | |
| timeoutMs: 10_000, | |
| fallbackErrorDetail: "git checkout failed", | |
| }, |
In this repo, switching between the two branches rewrites about 6,000 files, some through Git LFS, so the checkout takes longer than 10 seconds. The timeout kills git after it has written part of the target branch's files, but before it updates the index and HEAD. Git can't roll back an interrupted checkout, so the working tree is left mixed and the UI shows only a generic failure.
Long-running commands such as push already pass timeoutMs: null (L2660). Checkout changes the working tree, so killing it partway does more damage than letting it finish. Running it without a timeout, or warning that the working tree may be partially updated when it fails, would avoid this.
Steps to reproduce
- Open a repo where switching between two branches rewrites enough files that
git checkouttakes more than 10 seconds (here about 6,000 files, with Git LFS). - Switch to the other branch with the branch picker.
- After about 10 seconds the switch fails.
git statusshows thousands of changes and the old branch is still checked out.
Running the same git checkout <branch> in a terminal completes normally.
Version
0.1.1-nightly.20261019.3348
Environment
Windows desktop app, server in WSL2 (Ubuntu 24.04.4), git 2.43.0, git-lfs 3.4.1
Evidence
server.trace.ndjson:
GitVcsDriver.switchRef.checkout durationMs=10025.5 2026-10-20 11:45:32
GitVcsDriver.switchRef.checkout durationMs=10028.8 2026-10-20 12:06:23
GitCommandError: Git command failed in GitVcsDriver.switchRef.checkout (<repo>): Git command timed out.
cause: InterruptError: All fibers interrupted without error
at runGitCommand
git status --short | cut -c1-2 | sort | uniq -c (after the second failure)
3918 D
2241 M
50 ??Related issues
#15541 hits the fixed 5-minute git timeout during worktree creation. It's the same kind of problem, but a different code path and limit, so a fix there wouldn't cover branch switching.
Fix applied or workaround
Restored the old branch with git reset --hard HEAD and git clean -fd, then ran git checkout from a terminal, which completed.
Filed by
Claude Code (claude-opus-5-5) in a T3 Code thread
Activity
juliusmarminge commentedon Oct 21, 2026
Reproduced on current main 70e5e384da using the web dev app with a Linux server. Switching from
oldtotargetthrough the branch picker in a disposable repository with a 15-second Git smudge filter failed after 10,008 ms. HEAD remained onold, while a tracked file containedtargetcontent. The same checkout in a terminal completed in 15.149 seconds. This reproduces the interrupted-checkout failure without the private monorepo; Windows/WSL2 and Git LFS remain unverified.mahmoodnizamani94-png commentedon Nov 3, 2026
Hit this same 10-second timeout in
GitVcsDriver.switchRef.checkoutonv0.1.6(latest stable release, not nightly; Linux x64, T3 Code Desktop 0.1.6 stable, git 2.56.0), filed with full details in #30368.One extra way this bites people is on a blobless partial clone (
remote.origin.partialclonefilter=blob:none) when switching to an orphan/deployment branch that only holds binaries and none of the main source tree:git checkoutunlinks all existing tracked files from the working directory right away (within ~20ms), then starts downloading the missing blobs for the target branch over the network.durationMs: 10014.5),GitVcsDriver.switchRef.checkoutkillsgit checkoutbefore it finishes fetching the blobs or updatingHEAD.HEADstays on the previous branch with the working tree completely wiped. If you then switch tomain, git only writes out the few files that differ between the previous branch andmain, leaving the rest of the repo deleted on disk.