stablyai/orca · warning

Local branch "${branchName}" is checked out in another workt

Error message

Local branch "${branchName}" is checked out in another worktree.

What it means

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.

Source

Thrown at src/main/git/worktree.ts:1393

export async function forceDeleteLocalBranch(
  repoPath: string,
  branchName: string,
  expectedHead: string,
  runGit: (args: string[], cwd: string) => Promise<{ stdout: string; stderr: string }> = (
    args,
    cwd
  ) => gitExecFileAsync(args, { cwd })
): Promise<void> {
  if (!branchName || branchName.includes('\0')) {
    throw new Error('Invalid branch name')
  }
  if (!expectedHead) {
    throw new Error(
      `Cannot force-delete local branch "${branchName}" without the commit Git preserved.`
    )
  }
  if (await isLocalBranchCheckedOut(repoPath, branchName, runGit)) {
    throw new Error(`Local branch "${branchName}" is checked out in another worktree.`)
  }
  // Why: stale toast actions must not delete a branch that moved; `update-ref -d` deletes only if the ref still == expectedHead.
  try {
    await runGit(['update-ref', '-d', `refs/heads/${branchName}`, expectedHead], repoPath)
  } catch {
    throw new Error(
      `Local branch "${branchName}" changed after the workspace was deleted. Review it before deleting it.`
    )
  }
  if (await isLocalBranchCheckedOut(repoPath, branchName, runGit)) {
    try {
      await runGit(['update-ref', `refs/heads/${branchName}`, expectedHead, ''], repoPath)
    } catch (restoreError) {
      console.warn(
        `[git] Failed to restore local branch "${branchName}" after concurrent checkout`,
        restoreError
      )
    }

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Run `git worktree list` and identify which worktree has the branch checked out.
  2. Switch that worktree to a different branch (e.g. main) or remove the worktree entirely.
  3. Retry the delete once `git branch --all` no longer shows the branch under any worktree's HEAD.
  4. If a stale registration is to blame, resolve it with `git worktree prune` first.
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check via the same primitive the function uses internally.
import { isLocalBranchCheckedOut } from './worktree'
async function assertBranchNotCheckedOut(repoPath: string, branch: string) {
  if (await isLocalBranchCheckedOut(repoPath, branch)) {
    throw new Error(`Switch or remove the other worktree on ${branch} first.`)
  }
}

Try / catch

try {
  await forceDeleteLocalBranch(repoPath, branch, head)
} catch (err) {
  if (/checked out in another worktree/.test((err as Error).message)) {
    promptSwitchOrRemoveOtherWorktree(branch)
  } else throw err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/fe7d6a6f850d0438. Report an issue: GitHub.