stablyai/orca · error · Error

Cannot safely offer force-delete for preserved branch "${res

Error message

Cannot safely offer force-delete for preserved branch "${result.preservedBranch.branchName}" without its saved commit.

What it means

Thrown by rememberPreservedBranchCleanupTarget when a RemoveWorktreeResult reports a preservedBranch but neither result.preservedBranch.head nor the fallbackHead (the registered worktree's HEAD) is available. Without a concrete commit SHA, Orca refuses to register a force-delete target because it cannot prove which commit to delete. This is a defensive invariant inside the remove flow, not a user-input error.

Source

Thrown at src/main/ipc/worktrees.ts:545

  hostId: ExecutionHostId
  branchName: string
  head: string
  pushTarget?: GitPushTarget
}

const preservedBranchCleanupByScope = new Map<string, PreservedBranchCleanupTarget>()

function rememberPreservedBranchCleanupTarget(
  worktreeId: string,
  hostId: ExecutionHostId,
  result: RemoveWorktreeResult | undefined,
  fallbackHead: string | undefined,
  pushTarget: GitPushTarget | undefined
): void {
  if (result?.preservedBranch) {
    const head = result.preservedBranch.head ?? fallbackHead
    if (!head) {
      throw new Error(
        `Cannot safely offer force-delete for preserved branch "${result.preservedBranch.branchName}" without its saved commit.`
      )
    }
    preservedBranchCleanupByScope.set(preservedBranchCleanupScopeKey({ worktreeId, hostId }), {
      worktreeId,
      hostId,
      branchName: result.preservedBranch.branchName,
      head,
      ...(pushTarget ? { pushTarget } : {})
    })
    return
  }
  preservedBranchCleanupByScope.delete(preservedBranchCleanupScopeKey({ worktreeId, hostId }))
}

function preserveBranchHeadFallback(
  result: RemoveWorktreeResult | undefined,
  fallbackHead: string | undefined

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Ensure the Git worktree list reports a HEAD for that worktree (check `git worktree list --porcelain` on the host).
  2. If using an SSH provider, confirm the provider version returns head in its worktree listings.
  3. Treat this as an internal defect: capture the remove args and the worktree list at the time of failure and report it, since the caller cannot supply the missing commit safely.
Defensive patterns

Strategy: try-catch

Try / catch

// In the remove flow, guard the remember call so a missing head does not abort cleanup.
try {
  rememberPreservedBranchCleanupTarget(worktreeId, hostId, removalResult, fallbackHead, pushTarget)
} catch (e) {
  // Log and skip registering a force-delete target; the branch can still be deleted manually later.
  console.warn('[worktrees] cannot register preserved-branch cleanup (no head)', e)
}

Prevention

When it happens

Trigger: A worktrees:remove whose Git result preserved a branch (preserveBranchOnDelete) but the worktree list entry carried no resolvable head, and the registeredWorktree.head passed as fallback was also undefined.

Common situations: Git reported a detached/unborn HEAD for the worktree, a remote SSH provider returned a worktree entry without head metadata, or an older provider implementation omitted the head field. Usually points to an unexpected Git/provider state rather than a config mistake.

Related errors


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