{"record":{"id":"c4117ac30198d3b2","repo":"zed-industries/zed","slug":"git-worktree-directory-resolved-to-resolved-w","errorCode":null,"errorMessage":"git.worktree_directory resolved to {resolved:?}, which is outside the project root and its parent directory. It must resolve to a subdirectory of {repository_anchor_path:?} or a sibling of it.","messagePattern":"git\\.worktree_directory resolved to (.+?), which is outside the project root and its parent directory\\. It must resolve to a subdirectory of (.+?) or a sibling of it\\.","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/project/src/git_store.rs","lineNumber":10528,"sourceCode":"        path::normalize_path(&joined)\n    };\n    let resolved = if resolved.starts_with(repository_anchor_path) {\n        resolved\n    } else if let Some(repo_dir_name) = repository_anchor_path\n        .file_name()\n        .and_then(|name| name.to_str())\n    {\n        path_style.join_path(&resolved, repo_dir_name)?\n    } else {\n        resolved\n    };\n\n    let parent = repository_anchor_path\n        .parent()\n        .unwrap_or(repository_anchor_path);\n\n    if !resolved.starts_with(parent) {\n        anyhow::bail!(\n            \"git.worktree_directory resolved to {resolved:?}, which is outside \\\n             the project root and its parent directory. It must resolve to a \\\n             subdirectory of {repository_anchor_path:?} or a sibling of it.\"\n        );\n    }\n\n    Ok(resolved)\n}\n\nasync fn remove_empty_managed_worktree_ancestors(fs: &dyn Fs, child_path: &Path, base_path: &Path) {\n    let mut current = child_path;\n    while let Some(parent) = current.parent() {\n        if parent == base_path {\n            break;\n        }\n        if !parent.starts_with(base_path) {\n            break;\n        }","sourceCodeStart":10510,"sourceCodeEnd":10546,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/project/src/git_store.rs#L10510-L10546","documentation":"After joining the relative setting onto the repository anchor path and normalizing, the resolved directory must start with either the repository directory or its parent (crates/project/src/git_store.rs:10528). Values whose '..' traversal escapes both - e.g. \"../..\" - are rejected so Zed never manages worktrees outside the project root or its sibling directory.","triggerScenarios":"git.worktree_directory containing enough '..' segments to resolve above the repository's parent directory, for example \"../..\" or \"subdir/../../..\", when a worktree is created.","commonSituations":"Trying to gather all worktrees in a central folder like ~/worktrees; deeply nested repositories where \"../..\" looks harmless.","solutions":["Keep worktrees inside the repository: \"tools/worktrees\" or \".worktrees\"","Keep them directly beside the repository: \"../<repo-name>-worktrees\"","For centralized locations, create a symlink from the allowed sibling directory instead"],"exampleFix":"// settings.json - before\n{ \"git\": { \"worktree_directory\": \"../..\" } }\n\n// settings.json - after\n{ \"git\": { \"worktree_directory\": \"../acme-worktrees\" } }","handlingStrategy":"validation","validationCode":"// Mirror Zed's containment rule before creating worktrees programmatically\nlet joined = repository_anchor_path.join(trimmed_setting);\nlet resolved = normalize_path(joined);\nlet parent = repository_anchor_path.parent().unwrap_or(repository_anchor_path);\nif !resolved.starts_with(parent) {\n    return Err(\"worktree directory escapes the repository root and its parent\".into());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep worktree_directory inside the repo or a named sibling of it","Compute the resolved path and check prefix containment before passing user config onward"],"tags":["git","worktree","settings","path-traversal","configuration"],"backgroundTag":"path-escapes-allowed-root","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"}