Skip to content

fix(desktop): classify detached-HEAD main-repo open as typed BAD_REQUEST - #6258

Merged
saddlepaddle merged 1 commit into
mainfrom
sentry/detached-head-open-main
Aug 13, 2026
Merged

saddlepaddle merged 1 commit into
mainfrom
sentry/detached-head-open-main

Conversation

@Kitenite

@Kitenite Kitenite commented Aug 7, 2026 •

Copy link
Copy Markdown
Member

Problem

Opening a project's main repository as a workspace (workspaces.openMainRepoWorkspace) throws a plain Error("Could not determine current branch") when the repo has no current branch. The tRPC sentryMiddleware reports this as an INTERNAL_SERVER_ERROR, so an expected user-repo state shows up in Sentry as a 500 (DESKTOP-JM, 3 events on 1.15.1).

Root cause

When the main repo is on a detached HEAD (or an unborn branch), getCurrentBranch returns nothing and the guard at the top of openMainRepoWorkspace throws an untyped Error. Per the classification contract (#6164), expected domain states must be translated into non-500 TRPCErrors at the throw site — this one never was.

Fix

Replace the plain throw with a typed TRPCError:

  • code: "BAD_REQUEST" — matching the existing detached-HEAD classification in getLocalBranchOrThrow (routers/changes/git-operations.ts), whose message style this also follows.
  • cause: { kind: "DETACHED_HEAD" } — a plain-object, kind-discriminated cause that the existing errorFormatter in src/lib/trpc/index.ts already forwards to the renderer.
  • User-actionable message: "Cannot open this repository from detached HEAD. Please checkout a branch and try again."

No filter, no middleware change — genuine unexpected failures on this path still reach Sentry as before.

Verification

  • bunx biome check apps/desktop/src/lib/trpc/routers/workspaces/procedures/create.ts
    Checked 1 file in 19ms. No fixes applied.
    
  • cd apps/desktop && bun run typecheck
    $ tsr generate
    $ tsc --noEmit
    exit=0
    
  • No existing tests cover the changed guard (the adjacent external-worktree-import.test.ts tests utils/git only), so no test run applies.

Refs DESKTOP-JM

https://claude.ai/code/session_2bf90175-44a5-44e3-be07-aeed3182571a


Summary by cubic

Treat opening the main repo on a detached HEAD as a BAD_REQUEST instead of a 500, with a clear action message. Aligns with DESKTOP-JM and keeps this expected state out of Sentry server errors.

Written for commit 2315ab6. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes
    • Improved error handling when opening a workspace from a detached Git HEAD.
    • Displays a clear, user-facing message instead of a generic error.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 38d6f981-afb0-461c-bbe5-6f85d9923d0d

📥 Commits

Reviewing files that changed from the base of the PR and between ddd3d48 and 2315ab6.

📒 Files selected for processing (1)
  • apps/desktop/src/lib/trpc/routers/workspaces/procedures/create.ts

📝 Walkthrough

Walkthrough

The workspace creation procedure now reports detached HEAD states with a TRPCError using the BAD_REQUEST code and DETACHED_HEAD cause.

Changes

Workspace error handling

Layer / File(s) Summary
Detached HEAD validation
apps/desktop/src/lib/trpc/routers/workspaces/procedures/create.ts
Detached HEAD handling now throws a TRPCError with a user-facing message, BAD_REQUEST code, and DETACHED_HEAD cause.

Estimated code review effort: 1 (Trivial) | ~2 minutes

Suggested reviewers: saddlepaddle

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title uses conventional commit format and clearly identifies the typed BAD_REQUEST classification for detached-HEAD repository opening.
Description check ✅ Passed The description explains the problem, root cause, fix, and verification results with sufficient technical detail.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sentry/detached-head-open-main

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/lib/trpc/routers/workspaces/procedures/create.ts">

<violation number="1" location="apps/desktop/src/lib/trpc/routers/workspaces/procedures/create.ts:748">
P2: Because getCurrentBranch swallows every git failure and returns null, a genuine error (not-a-git-repo, git binary/permission failure) now surfaces to the user as 'detached HEAD' and is no longer reported to Sentry — so unexpected failures on this path no longer reach Sentry 'as before' as the PR states. Consider distinguishing a real git error (e.g. let getCurrentBranch propagate or check repo validity) and only classify detached HEAD as BAD_REQUEST.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

input.branch || (await getCurrentBranch(project.mainRepoPath));
if (!branch) {
throw new Error("Could not determine current branch");
throw new TRPCError({

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.

P2: Because getCurrentBranch swallows every git failure and returns null, a genuine error (not-a-git-repo, git binary/permission failure) now surfaces to the user as 'detached HEAD' and is no longer reported to Sentry — so unexpected failures on this path no longer reach Sentry 'as before' as the PR states. Consider distinguishing a real git error (e.g. let getCurrentBranch propagate or check repo validity) and only classify detached HEAD as BAD_REQUEST.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/lib/trpc/routers/workspaces/procedures/create.ts, line 748:

<comment>Because getCurrentBranch swallows every git failure and returns null, a genuine error (not-a-git-repo, git binary/permission failure) now surfaces to the user as 'detached HEAD' and is no longer reported to Sentry — so unexpected failures on this path no longer reach Sentry 'as before' as the PR states. Consider distinguishing a real git error (e.g. let getCurrentBranch propagate or check repo validity) and only classify detached HEAD as BAD_REQUEST.</comment>

<file context>
@@ -745,7 +745,12 @@ export const createCreateProcedures = () => {
 					input.branch || (await getCurrentBranch(project.mainRepoPath));
 				if (!branch) {
-					throw new Error("Could not determine current branch");
+					throw new TRPCError({
+						code: "BAD_REQUEST",
+						message:
</file context>

@saddlepaddle
saddlepaddle merged commit e65d7ac into main Aug 13, 2026
12 checks passed
@saddlepaddle
saddlepaddle deleted the sentry/detached-head-open-main branch August 13, 2026 18:38
@github-actions

Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch

Thank you for your contribution! 🎉

saddlepaddle added a commit that referenced this pull request Aug 13, 2026
…y fix wave (#6437)

* fix(desktop,host-service): address unreviewed findings from the sentry fix wave

Four defects that automated reviewers flagged on PRs #6191, #6258, #6316
and #6318 and that were merged without anyone acting on them.

- host-service-coordinator: crash reports redacted the child's own auth
  secret but not the cloud credential the coordinator also injects into
  its env, so a logged Authorization header could reach Sentry. Replace
  the single replacement with a per-instance redaction list.
- workspaces/create: getCurrentBranch() returns null for a detached HEAD
  and for any git failure alike, so a missing repo or a permission wall
  was reported to the user as a detached HEAD and stopped being visible
  in Sentry. Confirm HEAD is genuinely detached first.
- mesh-gradient: the WebGL probe leaked a context per mount, which can
  exhaust the browser's context budget and pin the real gradient to the
  static fallback. Release the probe and cache the result.
- workspace-creation: existsSync() is true for a regular file, so a repo
  path pointing at a file passed the directory guard.

* refactor(desktop): read HEAD once via a discriminated result instead of a second git client
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants