{"record":{"id":"fe7d6a6f850d0438","repo":"stablyai/orca","slug":"local-branch-branchname-is-checked-out-in-ano","errorCode":null,"errorMessage":"Local branch \"${branchName}\" is checked out in another worktree.","messagePattern":"Local branch \"(.+?)\" is checked out in another worktree\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/main/git/worktree.ts","lineNumber":1393,"sourceCode":"export async function forceDeleteLocalBranch(\n  repoPath: string,\n  branchName: string,\n  expectedHead: string,\n  runGit: (args: string[], cwd: string) => Promise<{ stdout: string; stderr: string }> = (\n    args,\n    cwd\n  ) => gitExecFileAsync(args, { cwd })\n): Promise<void> {\n  if (!branchName || branchName.includes('\\0')) {\n    throw new Error('Invalid branch name')\n  }\n  if (!expectedHead) {\n    throw new Error(\n      `Cannot force-delete local branch \"${branchName}\" without the commit Git preserved.`\n    )\n  }\n  if (await isLocalBranchCheckedOut(repoPath, branchName, runGit)) {\n    throw new Error(`Local branch \"${branchName}\" is checked out in another worktree.`)\n  }\n  // Why: stale toast actions must not delete a branch that moved; `update-ref -d` deletes only if the ref still == expectedHead.\n  try {\n    await runGit(['update-ref', '-d', `refs/heads/${branchName}`, expectedHead], repoPath)\n  } catch {\n    throw new Error(\n      `Local branch \"${branchName}\" changed after the workspace was deleted. Review it before deleting it.`\n    )\n  }\n  if (await isLocalBranchCheckedOut(repoPath, branchName, runGit)) {\n    try {\n      await runGit(['update-ref', `refs/heads/${branchName}`, expectedHead, ''], repoPath)\n    } catch (restoreError) {\n      console.warn(\n        `[git] Failed to restore local branch \"${branchName}\" after concurrent checkout`,\n        restoreError\n      )\n    }","sourceCodeStart":1375,"sourceCodeEnd":1411,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/git/worktree.ts#L1375-L1411","documentation":"Thrown by forceDeleteLocalBranch on the FIRST isLocalBranchCheckedOut check, before any deletion is attempted. The branch is currently checked out in some worktree, so deleting its ref would corrupt that worktree's HEAD. Unlike the post-delete variant (1066), no git mutation has happened yet — this is a pure precondition failure.","triggerScenarios":"User opened the same branch in two worktrees (e.g. main worktree + a feature worktree on the same branch); a worktree was created on the branch and not switched away before the delete action fired; an orphaned worktree admin entry still records the branch as checked out.","commonSituations":"Multi-worktree workflow where the user forgot a second worktree is on the branch; a stale worktree registration (linked to 1061) makes git believe the branch is still checked out somewhere.","solutions":["Run `git worktree list` and identify which worktree has the branch checked out.","Switch that worktree to a different branch (e.g. main) or remove the worktree entirely.","Retry the delete once `git branch --all` no longer shows the branch under any worktree's HEAD.","If a stale registration is to blame, resolve it with `git worktree prune` first."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-check via the same primitive the function uses internally.\nimport { isLocalBranchCheckedOut } from './worktree'\nasync function assertBranchNotCheckedOut(repoPath: string, branch: string) {\n  if (await isLocalBranchCheckedOut(repoPath, branch)) {\n    throw new Error(`Switch or remove the other worktree on ${branch} first.`)\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await forceDeleteLocalBranch(repoPath, branch, head)\n} catch (err) {\n  if (/checked out in another worktree/.test((err as Error).message)) {\n    promptSwitchOrRemoveOtherWorktree(branch)\n  } else throw err\n}","preventionTips":["Before queuing a branch delete, confirm no other worktree is on that branch.","Switch worktrees off the branch as part of the worktree-removal flow.","Run `git worktree list` in CI/test fixtures to catch checked-out branches."],"tags":["git","branch","worktree","precondition","concurrency"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}