stablyai/orca · error · Error

Repo not found: ${repoId}

Error message

Repo not found: ${repoId}

What it means

Thrown at the top of the worktrees:remove handler when getRepoForWorktreeRemoval returns undefined. That helper refuses to guess: it returns undefined if the repoId+hostId filter matches more than one owner, matches none, or the legacy getRepo fallback disagrees with the host scope. Deletion must resolve a single owning repo.

Source

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

      return runtime.resolveManagedMrBase({
        repoSelector: `id:${args.repoId}`,
        mrIid: args.mrIid,
        sourceBranch: args.sourceBranch,
        targetBranch: args.targetBranch,
        isCrossRepository: args.isCrossRepository
      })
    }
  )

  const worktreeRemovalsInFlight = new Map<string, WorktreeRemovalInFlight>()

  ipcMain.handle(
    'worktrees:remove',
    async (_event, args: RemoveWorktreeArgs): Promise<RemoveWorktreeResult> => {
      const { repoId, worktreePath } = parseWorktreeId(args.worktreeId)
      const repo = getRepoForWorktreeRemoval(store, repoId, args.hostId)
      if (!repo) {
        throw new Error(`Repo not found: ${repoId}`)
      }
      // The resolved repo supplies host ownership when legacy callers omit args.hostId.
      const removalHostId = getRepoExecutionHostId(repo)
      const inFlightKey = getWorktreeRemovalInFlightKey(args.worktreeId, removalHostId)
      const optionsKey = getWorktreeRemovalOptionsKey(args)
      const inFlightRemoval = worktreeRemovalsInFlight.get(inFlightKey)
      if (inFlightRemoval) {
        if (inFlightRemoval.optionsKey === optionsKey) {
          return inFlightRemoval.promise
        }
        throw new Error(`Worktree deletion already in progress: ${args.worktreeId}`)
      }

      // Why: concurrent stale-toast/double-click/sidebar races can hit the same worktree; share the op so only one path touches Git and disk.
      const removal = (async (): Promise<RemoveWorktreeResult> => {
        // Why: worktree.create is traced; delete freezes were invisible without a matching worktree.remove parent span.
        return withWorktreeSpan({ stage: 'remove', path: worktreePath }, async () => {
          if (isFolderRepo(repo)) {

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Pass the correct args.hostId matching the worktree's owning host so getRepoForWorktreeRemoval resolves exactly one repo.
  2. Refresh repo/worktree state and remove a still-registered worktree.
  3. If the repo genuinely has multiple host owners with the same id, disambiguate by host before calling remove.
Defensive patterns

Strategy: validation

Validate before calling

// Resolve exactly one owning repo before removing.
const repo = await invoke('repos:resolveForRemoval', { repoId, hostId })
if (!repo) {
  throw new Error(`No unique repo owner for ${repoId} on host ${hostId}`)
}
await invoke('worktrees:remove', { worktreeId, hostId })

Prevention

When it happens

Trigger: A worktrees:remove call whose repoId (parsed from worktreeId) is unknown, or whose args.hostId matches multiple host-owned copies of the same repo id (ambiguous ownership), or whose hostId doesn't match any owner.

Common situations: Renderer sends a stale worktreeId after the repo was removed; a worktree id is shared across a local and an SSH-owned copy of the same repo id and the caller omitted/ mismatched hostId; or the repo was deleted between listing and removal.

Related errors


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