{"record":{"id":"73ffa2bcd52b132e","repo":"coleam00/Archon","slug":"cannot-delete-branch-options-branchname-work","errorCode":null,"errorMessage":"Cannot delete branch '${options.branchName}': worktree path gone and no canonicalRepoPath provided","messagePattern":"Cannot delete branch '(.+?)': worktree path gone and no canonicalRepoPath provided","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/isolation/src/providers/worktree.ts","lineNumber":257,"sourceCode":"    if (!pathExists) {\n      getLog().debug({ worktreePath }, 'worktree_path_already_removed');\n      result.worktreeRemoved = true; // Already gone counts as removed\n      result.directoryClean = true;\n    }\n\n    // Get canonical repo path - use provided path or derive from worktree\n    let repoPath: string;\n    if (options?.canonicalRepoPath) {\n      repoPath = (await getGitCommandAnchors(options.canonicalRepoPath)).durable;\n    } else if (pathExists) {\n      repoPath = (await getGitCommandAnchors(worktreePath)).durable;\n    } else {\n      // Path doesn't exist and no canonicalRepoPath provided - can't clean up branch\n      // This is expected when worktree was already fully cleaned up externally\n      if (options?.branchName) {\n        const warning = `Cannot delete branch '${options.branchName}': worktree path gone and no canonicalRepoPath provided`;\n        getLog().warn({ worktreePath, branchName: options.branchName }, 'branch_cleanup_skipped');\n        result.warnings.push(warning);\n      }\n      return result;\n    }\n\n    // Only attempt worktree removal if path exists\n    if (pathExists) {\n      const gitArgs = ['-C', repoPath, 'worktree', 'remove'];\n      if (options?.force) {\n        gitArgs.push('--force');\n      }\n      gitArgs.push(worktreePath);\n\n      try {\n        await execFileAsync('git', gitArgs, { timeout: GIT_OPERATION_TIMEOUT_MS });\n        result.worktreeRemoved = true;\n      } catch (error) {\n        if (!this.isWorktreeMissingError(error)) {\n          throw error;","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/isolation/src/providers/worktree.ts#L239-L275","documentation":"Not a thrown error but a warning string recorded in destroy()'s result.warnings in packages/isolation/src/providers/worktree.ts. When the worktree path is already gone and no canonicalRepoPath was supplied, destroy cannot run 'git worktree remove' or resolve the repo, so a stale branch named via options.branchName cannot be pruned; the warning documents the skipped branch cleanup.","triggerScenarios":"Calling destroy({ branchName }) on a worktree whose directory no longer exists on disk, without providing canonicalRepoPath in options.","commonSituations":"A previous cleanup pass already deleted the worktree directory but not its branch; manual rm -rf of the worktree; calling destroy twice; CI re-running teardown after an earlier successful destroy.","solutions":["Pass canonicalRepoPath in the destroy options so the provider can delete the branch even when the worktree path is gone","Delete the branch manually: git -C <canonicalRepoPath> branch -D <branchName> (or git worktree prune first)","Treat the warning as benign if the worktree was already fully cleaned up externally, as the code notes","Make teardown idempotent: run git worktree prune and branch deletion as separate best-effort steps"],"exampleFix":"// before\nawait provider.destroy({ worktreePath, branchName: 'archon/issue-42' });\n// after\nawait provider.destroy({\n  worktreePath,\n  branchName: 'archon/issue-42',\n  canonicalRepoPath: '/repos/main-checkout',\n});","handlingStrategy":"fallback","validationCode":"const pathExists = existsSync(worktreePath);\nconst repoExists = options.canonicalRepoPath ? existsSync(options.canonicalRepoPath) : false;\nif (!pathExists && options.branchName && !repoExists) {\n  console.warn(`Branch ${options.branchName} may be orphaned; no repo available to delete it`);\n}","typeGuard":"function hasBranchCleanupWarning(result: DestroyResult): boolean {\n  return result.warnings.some(w => w.startsWith(\"Cannot delete branch '\"));\n}","tryCatchPattern":"const result = await provider.destroy({ worktreePath, branchName, canonicalRepoPath });\nfor (const w of result.warnings) {\n  if (w.includes('Cannot delete branch')) {\n    getLog().warn({ worktreePath, w }, 'branch cleanup skipped; pruning manually');\n    await exec('git -C ' + canonicalRepoPath + ' worktree prune');\n    await exec('git -C ' + canonicalRepoPath + ' branch -D ' + branchName);\n  }\n}","preventionTips":["Always pass canonicalRepoPath when destroying a worktree whose branch you want gone","Treat destroy() as idempotent and inspect result.warnings, not just thrown errors","Run git worktree prune after external/manual worktree deletion","Make teardown a single tracked step so branch cleanup is not lost"],"tags":["worktree","git-branch","cleanup","warning"],"backgroundTag":"worktree-branch-cleanup-skipped","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}