{"record":{"id":"82aaac05d3c7afc9","repo":"zed-industries/zed","slug":"a-worktree-already-exists-at","errorCode":null,"errorMessage":"A worktree already exists at {}","messagePattern":"A worktree already exists at (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/git_ui_core/src/worktree_service.rs","lineNumber":495,"sourceCode":"    )>,\n    Vec<(PathBuf, PathBuf)>,\n)> {\n    let mut creation_infos = Vec::new();\n    let mut path_remapping = Vec::new();\n    let mut scheduled_paths: HashSet<PathBuf> = HashSet::default();\n\n    let worktree_name = worktree_name.unwrap_or_else(|| {\n        let existing_refs: Vec<&str> = existing_worktree_names.iter().map(|s| s.as_str()).collect();\n        worktree_names::generate_worktree_name(&existing_refs, rng)\n            .unwrap_or_else(|| \"worktree\".to_string())\n    });\n\n    for repo in git_repos {\n        let (work_dir, new_path, receiver) = repo.update(cx, |repo, _cx| {\n            let new_path =\n                repo.path_for_new_linked_worktree(&worktree_name, worktree_directory_setting)?;\n            if existing_worktree_paths.contains(&new_path) {\n                anyhow::bail!(\"A worktree already exists at {}\", new_path.display());\n            }\n            let work_dir = repo.work_directory_abs_path.clone();\n            // Only the first repo that resolves to a given target path\n            // actually creates the worktree; subsequent linked worktrees of\n            // the same repository just contribute a path remapping.\n            let receiver = if scheduled_paths.contains(&new_path) {\n                None\n            } else {\n                let target = git::repository::CreateWorktreeTarget::Detached {\n                    base_sha: base_ref.clone(),\n                };\n                Some(repo.create_worktree(target, new_path.clone()))\n            };\n            anyhow::Ok((work_dir, new_path, receiver))\n        })?;\n        path_remapping.push((work_dir.to_path_buf(), new_path.clone()));\n        if let Some(receiver) = receiver {\n            scheduled_paths.insert(new_path.clone());","sourceCodeStart":477,"sourceCodeEnd":513,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/git_ui_core/src/worktree_service.rs#L477-L513","documentation":"When Zed creates linked worktrees, it computes each repository's target directory via path_for_new_linked_worktree(worktree_name, dir). If that path is already present in existing_worktree_paths, the service bails rather than letting 'git worktree add' clobber or duplicate a checkout. It is a name/path collision detected up front.","triggerScenarios":"Calling multi-repo worktree creation with an explicit worktree_name that already exists on disk for one of the repos; two repositories in the project resolving to the same target directory for the chosen name; re-running the create-worktree flow with the same custom name after a previous run.","commonSituations":"User re-invokes worktree creation with a previously used name; stale worktree directories left behind after aborted runs; a fixed worktree_directory_setting that funnels every worktree to one location.","solutions":["Omit the explicit name so generate_worktree_name picks a unique one against existing refs, or choose a different name","If the old worktree is stale, remove it first (git worktree remove <path>, then git worktree prune)","If the name must be reused, move or retire the existing directory before creating again","Check worktree_directory_setting: a shared fixed directory makes collisions far more likely"],"exampleFix":"// before\nstart_worktree_creations(&repos, Some(\"feature-x\".into()), ..) // 'feature-x' already on disk -> bail\n\n// after: let the generator avoid existing names\nstart_worktree_creations(&repos, None, ..)","handlingStrategy":"validation","validationCode":"// before asking the service to create worktrees\nlet target = repo.read(cx).path_for_new_linked_worktree(&name, dir)?;\nif existing_worktree_paths.contains(&target) {\n    // pick a different name or prune the stale worktree instead of erroring\n}","typeGuard":null,"tryCatchPattern":"match start_worktree_creations(&repos, Some(name.clone()), ..) {\n    Ok(result) => { /* ... */ }\n    Err(err) if err.to_string().contains(\"worktree already exists\") => {\n        // regenerate a unique name and retry once, or offer to open the existing worktree\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Prefer generated worktree names over fixed custom ones in multi-repo projects","Re-scan existing worktree paths immediately before creation instead of trusting a stale snapshot","Prune stale worktrees (git worktree prune) in maintenance flows","Avoid a shared fixed worktree_directory_setting that funnels all worktrees to one path"],"tags":["git","worktree","filesystem","zed","path-collision"],"backgroundTag":"path-already-exists","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}