Yeachan-Heo/oh-my-codex · error · Error
worktree_path_conflict
worktree_path_conflict
Error message
worktree_path_conflict:${plan.worktreePath} What it means
Thrown by ensureWorktree when the target directory for a new git worktree already exists on disk. The library refuses to clobber an existing path because it cannot know whether it holds unrelated files or a stale worktree. This is a pre-flight safety check performed before running `git worktree add`.
Source
Thrown at src/team/worktree.ts:437
reused: true,
createdBranch: false,
...(dirty ? { dirty: true } : {}),
} satisfies EnsureWorktreeResult;
if (plan.branchName) {
upsertCurrentTaskBaseline(plan.repoRoot, {
branch_name: plan.branchName,
worktree_path: reused.worktreePath,
base_ref: plan.baseRef,
status: 'active',
});
}
return reused;
}
if (existsSync(plan.worktreePath)) {
throw new Error(`worktree_path_conflict:${plan.worktreePath}`);
}
if (plan.branchName && hasBranchInUse(allWorktrees, plan.branchName, plan.worktreePath)) {
throw new Error(`branch_in_use:${plan.branchName}`);
}
if (plan.branchName) {
assertCurrentTaskBranchAvailable(plan.repoRoot, plan.branchName, plan.worktreePath);
}
mkdirSync(dirname(plan.worktreePath), { recursive: true });
const branchAlreadyExisted = plan.branchName ? branchExists(plan.repoRoot, plan.branchName) : false;
const addArgs = ['worktree', 'add'];
if (plan.detached) {
addArgs.push('--detach', plan.worktreePath, plan.baseRef);
} else if (branchAlreadyExisted) {
addArgs.push(plan.worktreePath, plan.branchName as string);View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Remove or rename the existing directory: rm -rf <plan.worktreePath> then retry ensureWorktree
- Run `git worktree prune` in the repo root to clear stale worktree metadata and retry
- If the directory is a valid existing worktree you want to reuse, route the call through the reuse path (the code just above returns `reused`) instead of the create path
- Change the plan's branchName/slug so the derived worktreePath is unique per concurrent run
Example fix
// before
const ensured = ensureWorktree({ repoRoot, branchName: 'fix', worktreePath: '.worktrees/fix' }); // dir exists -> worktree_path_conflict
// after
execSync('git worktree prune', { cwd: repoRoot });
if (existsSync(worktreePath)) rmSync(worktreePath, { recursive: true, force: true });
const ensured = ensureWorktree({ repoRoot, branchName: 'fix', worktreePath: '.worktrees/fix' }); Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from 'node:fs';
import { resolve } from 'node:path';
function ensureWorktreePathFree(worktreePath: string): boolean {
return !existsSync(resolve(worktreePath));
} Try / catch
try {
ensureWorktree(plan);
} catch (e) {
if (e instanceof Error && e.message.startsWith('worktree_path_conflict:')) {
// stale dir: prune/remove then retry once
} else throw e;
} Prevention
- Derive worktree paths from unique branch names or run ids
- Always tear down worktrees in a finally block, including on signal/timeout
- Run git worktree prune before provisioning in CI
When it happens
Trigger: Calling ensureWorktree with a plan whose plan.worktreePath resolves to an existing directory — e.g. a previous worktree was left behind without `git worktree prune`, or a crashed run did not clean up its .worktrees/<slug> directory, or two plans computed the same path slug.
Common situations: Concurrent team runs deriving the same worktree path; leftover directories after a hard kill (SIGKILL, CI timeout) between add and cleanup; manually created directories colliding with the worktree naming scheme; stale worktree metadata after the branch was deleted outside the tool.
Related errors
- branch_in_use
- (result.stderr || '').trim() || `git ${args.join(' ')} faile
- (result.stderr || '').trim() || `git status failed for ${wor
- autoresearch_reset_requires_clean_worktree
- worktree_not_planned:${workerName}
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/6693cb5f2a0bf515.
Report an issue: GitHub.