Skip to content

fix(server): explain switchRef checkout failures with the fix to try next - #9378

Open
ImBIOS wants to merge 1 commit into
pingdotgg:mainfrom
ImBIOS:fix/switchref-actionable-error-7928
Open

fix(server): explain switchRef checkout failures with the fix to try next#9378
ImBIOS wants to merge 1 commit into
pingdotgg:mainfrom
ImBIOS:fix/switchref-actionable-error-7928

Conversation

@ImBIOS

@ImBIOS ImBIOS commented Sep 3, 2026

Copy link
Copy Markdown

Every switchRef checkout failure surfaced as Git command failed in GitVcsDriver.switchRef.checkout: git checkout failed because 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
switchRef no longer surfaces every failed git checkout as a generic git checkout failed message. The driver runs checkout with allowNonZeroExit, classifies stderr locally via classifySwitchRefCheckoutError, and returns GitCommandError.detail as 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.ts lock in those messages and assert errors omit stderr.

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.switchRef checkout failures

  • Adds classifySwitchRefCheckoutError to map Git stderr patterns (worktree conflicts, overwritten uncommitted changes, missing refs) to fixed explanatory messages; unrecognized failures get a generic checkout-failed message.
  • switchRef now inspects nonzero checkout exits instead of using a fallback error, and returns a GitCommandError with checkout context, classified detail, exit code, and stdout/stderr lengths. Raw stderr is omitted from the returned error.
  • Adds integration tests covering uncommitted-changes, linked-worktree, and unknown-ref checkout failures.
  • Behavioral Change: switchRef checkout errors no longer expose raw Git stderr; consumers relying on stderr text must use the classified detail instead.
📊 Macroscope summarized 71f3b27. 1 file reviewed, 1 issue evaluated, 0 issues filtered, 1 comment posted

🗂️ Filtered Issues

…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.
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Sep 3, 2026
// 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();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ 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,
},
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

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.";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 71f3b27. Configure here.

@macroscopeapp

macroscopeapp Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: 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:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant