stablyai/orca · error · Error

Cannot delete the project root workspace. Remove the folder

Error message

Cannot delete the project root workspace. Remove the folder project instead.

What it means

Thrown by both worktrees:remove and worktrees:forgetLocal when the target worktreeId equals the folder workspace root id (getFolderWorkspaceRootId). Folder workspaces share a single root directory; deleting it would destroy the project itself, so removal is blocked and the user is told to remove the folder project instead.

Source

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

      // 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)) {
            if (args.worktreeId === getFolderWorkspaceRootId(repo)) {
              throw new Error(
                'Cannot delete the project root workspace. Remove the folder project instead.'
              )
            }
            // Why: folder workspaces share one root, so there's no Git remove step to close shells; sweep PTYs before dropping metadata.
            await withWorktreeRemoveStageSpan('pty_sweep', 'folder', async () => {
              // Folder projects can be SSH-backed, so fence the sweep to the owning host exactly
              // like the git paths — the local inventory must never reach a remote workspace's id.
              // The resolved repo is authoritative here: path-derived metadata is shared by
              // same-id host copies and can describe a different owner's workspace.
              const ownerHost = parseExecutionHostId(removalHostId)
              const sshPtyProvider =
                ownerHost?.kind === 'ssh' ? getSshPtyProvider(ownerHost.targetId) : undefined
              const externalHost = ownerHost?.kind === 'ssh' || ownerHost?.kind === 'runtime'
              await killAllProcessesForWorktree(args.worktreeId, {
                runtime,
                resolvedWorktreeId: args.worktreeId,
                ...(ownerHost?.kind === 'ssh' ? { resolvedConnectionId: ownerHost.targetId } : {}),
                ...(ownerHost?.kind === 'runtime'

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Hide/disable delete for the folder root workspace in the UI and route project removal through the folder-project removal flow.
  2. For automation, detect folder repos and never call remove on getFolderWorkspaceRootId(repo).
  3. If the user wants the workspace gone, remove the folder project via its dedicated removal API.
Defensive patterns

Strategy: validation

Validate before calling

import { isFolderRepo } from '../../shared/folder-workspaces'
import { getFolderWorkspaceRootId } from '../../shared/folder-workspace-id'

function canDeleteWorktree(repo, worktreeId) {
  return !(isFolderRepo(repo) && worktreeId === getFolderWorkspaceRootId(repo))
}

Type guard

function isFolderRootWorkspace(repo: unknown, worktreeId: string): boolean {
  return !!repo && isFolderRepo(repo) && worktreeId === getFolderWorkspaceRootId(repo)
}

Prevention

When it happens

Trigger: Issuing worktrees:remove or worktrees:forgetLocal with the folder project's root workspace id for a folder-mode repo (isFolderRepo true).

Common situations: UI inadvertently offers a delete action on the folder root row, or a remote/automation client targets the root id of a folder workspace.

Related errors


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