fix(server): explain switchRef checkout failures with the fix to try next - #9378
fix(server): explain switchRef checkout failures with the fix to try next#9378ImBIOS wants to merge 1 commit into
Conversation
…next Every switchRef checkout failure surfaced as 'git checkout failed' because executeGit drops stderr on the wire. The checkout now classifies stderr into static sentences: uncommitted changes would be overwritten (commit/stash/discard), branch already checked out in another worktree, or ref not found (fetch and check the name). Raw stderr still never leaves the driver. Fixes pingdotgg#7928.
| // credentials), so every branch returns a fixed string that names the cause | ||
| // and the fix instead of echoing git's output. | ||
| function classifySwitchRefCheckoutError(stderr: string): string { | ||
| const normalized = stderr.toLowerCase(); |
There was a problem hiding this comment.
🟡 Medium vcs/GitVcsDriverCore.ts:451
switchRef returns the generic git checkout failed detail for translated worktree, overwrite, and missing-path diagnostics, so users lose the specific remediation this classifier is intended to provide. classifySwitchRefCheckoutError only matches English substrings, while switchRef runs checkout through executeGit without forcing LC_ALL: "C"; use executeGitWithStableDiagnostics or otherwise set that locale before parsing stderr.
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/vcs/GitVcsDriverCore.ts around line 451:
`switchRef` returns the generic `git checkout failed` detail for translated worktree, overwrite, and missing-path diagnostics, so users lose the specific remediation this classifier is intended to provide. `classifySwitchRefCheckoutError` only matches English substrings, while `switchRef` runs `checkout` through `executeGit` without forcing `LC_ALL: "C"`; use `executeGitWithStableDiagnostics` or otherwise set that locale before parsing stderr.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 71f3b27. Configure here.
| timeoutMs: 10_000, | ||
| allowNonZeroExit: true, | ||
| }, | ||
| ); |
There was a problem hiding this comment.
Classifier skips stable Git locale
Medium Severity
switchRef classifies English git checkout stderr without LC_ALL=C, so a localized Git still surfaces the generic git checkout failed message. Nearby removeWorktree already uses executeGitWithStableDiagnostics for the same style of matching.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 71f3b27. Configure here.
| function classifySwitchRefCheckoutError(stderr: string): string { | ||
| const normalized = stderr.toLowerCase(); | ||
| if (normalized.includes("used by worktree")) { | ||
| return "git checkout failed because the branch is already checked out in another worktree. Switch in that worktree or check out a different branch."; |
There was a problem hiding this comment.
Worktree matcher misses older Git
Medium Severity
classifySwitchRefCheckoutError only matches used by worktree, the Git 2.43+ wording. Older Git still emits is already checked out at, so worktree conflicts stay as the generic git checkout failed.
Reviewed by Cursor Bugbot for commit 71f3b27. Configure here.
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This production change alters switchRef checkout failure handling and relies on parsing Git’s English, version-dependent stderr while adding only current-version integration coverage. Localized Git output and older worktree wording can still produce the generic message, leaving the intended user guidance inconsistent. Not approved because:
Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more. |


Every switchRef checkout failure surfaced as
Git command failed in GitVcsDriver.switchRef.checkout: git checkout failedbecause the driver drops stderr on the wire, so users could not tell uncommitted changes, a worktree conflict, or a bad ref name apart (issue #7928).The checkout now classifies stderr into static sentences that name the cause and the fix: commit/stash/discard for uncommitted changes, switch in the other worktree for worktree conflicts, fetch and check the name for unknown refs. Raw stderr still never leaves the driver, so the redaction guarantee holds. This covers the switchRef construction that open PR #8645 deliberately left out of its shared-funnel classification.
Verification: vp test run apps/server/src/vcs/GitVcsDriverCore.test.ts (59 passed, 3 new), tsgo --noEmit clean for the touched files, vp lint + vp fmt + git diff --check clean.
Model: Muse Spark. Harness: OpenCode.
Note
Low Risk
Localized VCS error messaging for branch switch only; preserves existing stderr redaction and does not change successful checkout behavior.
Overview
switchRefno longer surfaces every failedgit checkoutas a genericgit checkout failedmessage. The driver runs checkout withallowNonZeroExit, classifies stderr locally viaclassifySwitchRefCheckoutError, and returnsGitCommandError.detailas fixed copy for common cases: uncommitted changes (commit/stash/discard), branch already checked out in another worktree, and missing refs (fetch and verify the name). Raw stderr still never leaves the server; failures log exit code and stderr length only.Three integration tests in
GitVcsDriverCore.test.tslock in those messages and assert errors omitstderr.Reviewed by Cursor Bugbot for commit 71f3b27. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Return classified structured errors for
GitVcsDriver.switchRefcheckout failuresclassifySwitchRefCheckoutErrorto map Git stderr patterns (worktree conflicts, overwritten uncommitted changes, missing refs) to fixed explanatory messages; unrecognized failures get a generic checkout-failed message.switchRefnow inspects nonzero checkout exits instead of using a fallback error, and returns aGitCommandErrorwith checkout context, classified detail, exit code, and stdout/stderr lengths. Raw stderr is omitted from the returned error.switchRefcheckout errors no longer expose raw Gitstderr; consumers relying on stderr text must use the classifieddetailinstead.📊 Macroscope summarized 71f3b27. 1 file reviewed, 1 issue evaluated, 0 issues filtered, 1 comment posted
🗂️ Filtered Issues