{"record":{"id":"586f357e231f150f","repo":"coleam00/Archon","slug":"worktree-at-worktreepath-was-reported-removed-b","errorCode":null,"errorMessage":"Worktree at ${worktreePath} was reported removed but is still registered in git","messagePattern":"Worktree at (.+?) was reported removed but is still registered in git","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/isolation/src/providers/worktree.ts","lineNumber":316,"sourceCode":"        result.directoryClean = true;\n      }\n    }\n\n    // Prune stale worktree references — runs even when path is already gone,\n    // because git may still have a stale ref for a manually-deleted worktree\n    try {\n      await execFileAsync('git', ['-C', repoPath, 'worktree', 'prune'], { timeout: 15000 });\n    } catch (_error) {\n      // Best-effort — pruning failure is not critical\n      getLog().debug({ repoPath }, 'worktree_prune_failed');\n    }\n\n    // Post-removal verification: confirm worktree is actually gone from git\n    if (result.worktreeRemoved) {\n      const stillRegistered = await this.isWorktreeRegistered(repoPath, worktreePath);\n      if (stillRegistered) {\n        result.worktreeRemoved = false;\n        const warning = `Worktree at ${worktreePath} was reported removed but is still registered in git`;\n        getLog().warn({ worktreePath, repoPath }, 'worktree_removal_verification_failed');\n        result.warnings.push(warning);\n      }\n    }\n\n    // Delete associated branch if provided (best-effort cleanup)\n    if (options?.branchName) {\n      result.branchDeleted = await this.deleteBranchTracked(repoPath, options.branchName, result);\n\n      // Delete remote branch if requested (e.g., after PR merge)\n      if (options.deleteRemoteBranch) {\n        result.remoteBranchDeleted = await this.deleteRemoteBranchTracked(\n          repoPath,\n          options.branchName,\n          result,\n          options.remote\n        );\n      }","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/isolation/src/providers/worktree.ts#L298-L334","documentation":"A post-removal verification warning recorded in destroy()'s result.warnings in packages/isolation/src/providers/worktree.ts. After git worktree remove reported success, destroy re-checks via isWorktreeRegistered; if git still lists the worktree (e.g. stale .git/worktrees metadata), worktreeRemoved is reset to false and this warning is appended.","triggerScenarios":"destroy() runs, worktreeRemoved is initially true, but isWorktreeRegistered(repoPath, worktreePath) still finds the path in 'git worktree list' / .git/worktrees metadata afterwards.","commonSituations":"Interrupted prior removals leaving stale .git/worktrees entries; removal of a locked worktree partially succeeding; git metadata corruption after a crash; network filesystems where metadata deletion lags.","solutions":["Run git worktree prune in the canonical repo to drop stale registration metadata, then verify with git worktree list","Check for a lock file (git worktree remove --force, or remove .git/worktrees/<name>/locked in the main checkout)","Inspect .git/worktrees/<name> in the main checkout and delete the stale directory manually if git prune does not clear it","After pruning, delete the branch if still desired, since destroy treated the worktree as unremoved"],"exampleFix":"// before\nawait provider.destroy({ worktreePath }); // warns: still registered in git\n// after\ngit -C /repos/main worktree prune\ngit -C /repos/main worktree list // confirm gone\nawait provider.destroy({ worktreePath }); // or treat as already removed","handlingStrategy":"validation","validationCode":"import { execFile } from 'node:child_process';\nconst { stdout } = await promisify(execFile)('git', ['-C', repoPath, 'worktree', 'list', '--porcelain']);\nif (stdout.includes(`worktree ${worktreePath}`)) {\n  await promisify(execFile)('git', ['-C', repoPath, 'worktree', 'prune']);\n}","typeGuard":"function hasStaleRegistrationWarning(result: DestroyResult): boolean {\n  return result.warnings.some(w => w.includes('still registered in git'));\n}","tryCatchPattern":"const result = await provider.destroy({ worktreePath, canonicalRepoPath: repoPath });\nif (hasStaleRegistrationWarning(result)) {\n  await execFile('git', ['-C', repoPath, 'worktree', 'prune']);\n  getLog().warn({ worktreePath }, 'pruned stale worktree registration after destroy');\n}","preventionTips":["Schedule or run git worktree prune after abnormal terminations and crashes","Never remove worktree directories with rm -rf alone; use git worktree remove","Check for lock files under .git/worktrees/<name>/ when removals stall","Inspect result.warnings after destroy instead of assuming success from absence of throws"],"tags":["worktree","git","stale-metadata","verification"],"backgroundTag":"worktree-removal-verification-failed","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}