stablyai/orca · error · Error
Failed to delete worktree at ${canonicalWorktreePath}.
Error message
Failed to delete worktree at ${canonicalWorktreePath}. What it means
Thrown when assertWorktreeUnlockedForRemoval(registeredWorktree) fails on the initial lock check before any destructive step. formatWorktreeRemovalError wraps the underlying message (Git lockfile/index.lock held by another client). A Git lock must block before archive hooks or linked-path cleanup mutate the workspace.
Source
Thrown at src/main/ipc/worktrees.ts:2638
preservedBranchCleanupByScope.delete(
preservedBranchCleanupScopeKey({
worktreeId: args.worktreeId,
hostId: removalHostId
})
)
notifyWorktreesChanged(mainWindow, repoId)
return {}
}
throw new Error(`Refusing to delete unregistered worktree path: ${worktreePath}`)
}
const canonicalWorktreePath = registeredWorktree.path
const deleteBranch = removedMeta?.preserveBranchOnDelete !== true
// Why: a Git lock must block before archive hooks or linked-path cleanup mutate the workspace; dirty-file force is separate.
try {
assertWorktreeUnlockedForRemoval(registeredWorktree)
} catch (error) {
throw new Error(
formatWorktreeRemovalError(error, canonicalWorktreePath, args.force ?? false)
)
}
// Why: a prior forced Windows recovery can delete the dir but leave a stale Git registration; verify before clearing metadata.
if (
!repo.connectionId &&
args.force === true &&
process.platform === 'win32' &&
(isWindowsAbsolutePathLike(canonicalWorktreePath) ||
!!localWorktreeGitOptions.wslDistro) &&
removedMeta &&
(await isAlreadyRemovedWorktreePath(
repo,
canonicalWorktreePath,
localWorktreeGitOptions
))
) {View on GitHub (pinned to 1136503c6a)
Solutions
- Ensure no other Git operation is running in that worktree, then retry removal.
- If a stale lockfile remains after a crash, remove it on the host and retry.
- Retry with force only after confirming the lock is genuinely stale, not a live operation.
Defensive patterns
Strategy: retry
Type guard
function isGitLockRemovalError(e: unknown): boolean {
return e instanceof Error && /lock/i.test(e.message)
} Try / catch
try {
await invoke('worktrees:remove', { worktreeId, force: false })
} catch (e) {
if (isGitLockRemovalError(e)) {
// Wait for the other Git op / remove stale lockfile, then retry once.
await invoke('worktrees:remove', { worktreeId, force: false })
} else throw e
} Prevention
- Ensure no other Git operation is running in the worktree before removing.
- Clear stale lockfiles left by crashed Git processes.
- Don't force past a lock unless it's confirmed stale.
When it happens
Trigger: A worktrees:remove where another Git process holds the worktree's lock (index.lock, or a `git` operation in progress in that worktree) at the moment removal begins.
Common situations: An IDE, a background fetch, a running commit/rebase, or a crashed Git process left a lockfile in the worktree; SSH host has a stale lock from a dropped session.
Related errors
- Refusing to delete unregistered worktree path: ${worktreePat
- Recorded benchmark helper PID now belongs to another process
- Cannot safely offer force-delete for preserved branch "${res
- No preserved branch cleanup is pending for "${branchName}".
- Repo not found: ${repoId}
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/9755e08116195120.
Report an issue: GitHub.