stablyai/orca · error

Git still reports a registration for "${worktreePath}" after

Error message

Git still reports a registration for "${worktreePath}" after pruning it.

What it means

Thrown by clearGitRegistrationForMissingWorktree after both `git worktree remove --force` AND `git worktree prune` ran, yet listWorktreesStrict (the strict, non-shared variant that does not silently treat an unreadable repo as empty) still returns a row for that path. It is a fail-closed guard: the removal left git's administrative state inconsistent, so the code refuses to report success. The strict scan is deliberate — an unreadable repo must not be misread as proof the row is gone.

Source

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

    await gitExecFileAsync(
      ['worktree', 'remove', '--force', worktreePath],
      gitExecOptions(repoPath, registrationOptions)
    )
    return
  } catch (error) {
    console.warn(
      `[git] Failed to deregister the moved worktree "${worktreePath}"; pruning instead`,
      error
    )
  }

  await gitExecFileAsync(['worktree', 'prune'], gitExecOptions(repoPath, registrationOptions))
  // Strict (not the shared scan): an unreadable repo must not read as proof that the row is gone.
  const stillRegistered = (await listWorktreesStrict(repoPath, registrationOptions)).some(
    (worktree) => areWorktreePathsEqual(worktree.path, worktreePath)
  )
  if (stillRegistered) {
    throw new Error(`Git still reports a registration for "${worktreePath}" after pruning it.`)
  }
}

async function deleteBranchAfterWorktreeRemoval(
  repoPath: string,
  branchName: string,
  branchHead: string,
  options: RemoveWorktreeOptions
): Promise<RemoveWorktreeResult> {
  try {
    // Why: also drop the now-orphaned branch so delete-worktree leaves none; `-d` (not `-D`) preserves
    // unmerged work, and forceBranchDelete opts into `-D` for failed-creation rollback.
    const branchDeleteResult = await deleteLocalBranchAfterWorktreeRemoval(
      repoPath,
      branchName,
      options.forceBranchDelete === true,
      options
    )

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Run `git worktree list --porcelain` in the main repo and confirm the stale row is still present.
  2. Manually `git worktree remove --force <path>` again, then `git worktree prune --verbose` and check the admin dir `.git/worktrees/<name>/` is gone.
  3. On Windows, close editors, stop the search indexer on that path, and retry removal.
  4. If the admin dir lingers, remove `.git/worktrees/<basename>/` by hand once you have confirmed no live worktree points at it.
  5. Retry the Orca removal once the manual prune succeeds.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check that the worktree admin entry exists and is prunable.
import { existsSync } from 'node:fs'
import { join } from 'node:path'
function worktreeAdminEntryExists(repoPath: string, worktreeBasename: string): boolean {
  return existsSync(join(repoPath, '.git', 'worktrees', worktreeBasename))
}

Try / catch

try {
  await removeWorktree(repoPath, worktreePath, options)
} catch (err) {
  if (/still reports a registration/.test((err as Error).message)) {
    // prompt the user to manually prune or close handles on Windows
    promptManualPrune(repoPath, worktreePath)
  } else throw err
}

Prevention

When it happens

Trigger: Removing a worktree whose directory was already deleted out-of-band while git's `.git/worktrees/<name>/` admin entry still references a stale absolute path; on Windows when a file handle (editor, indexer, antivirus) keeps the directory locked past prune; a worktree admin directory that lost its `gitdir` pointer so prune skips it; filesystem permissions that let prune read but not unlink the admin lock.

Common situations: Antivirus or search indexer holding a handle on Windows; the worktree was moved manually rather than via `git worktree move`; NFS/SMB mount flakiness where prune reads stale metadata; a concurrently running `git gc` rewriting worktree metadata mid-prune.

Related errors


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