zed-industries/zed · error · anyhow::Error
git.worktree_directory resolved to {resolved:?}, which is ou
Error message
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. What it means
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.
Source
Thrown at crates/project/src/git_store.rs:10528
path::normalize_path(&joined)
};
let resolved = if resolved.starts_with(repository_anchor_path) {
resolved
} else if let Some(repo_dir_name) = repository_anchor_path
.file_name()
.and_then(|name| name.to_str())
{
path_style.join_path(&resolved, repo_dir_name)?
} else {
resolved
};
let parent = repository_anchor_path
.parent()
.unwrap_or(repository_anchor_path);
if !resolved.starts_with(parent) {
anyhow::bail!(
"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."
);
}
Ok(resolved)
}
async fn remove_empty_managed_worktree_ancestors(fs: &dyn Fs, child_path: &Path, base_path: &Path) {
let mut current = child_path;
while let Some(parent) = current.parent() {
if parent == base_path {
break;
}
if !parent.starts_with(base_path) {
break;
}View on GitHub (pinned to f4178619ac)
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
Example fix
// settings.json - before
{ "git": { "worktree_directory": "../.." } }
// settings.json - after
{ "git": { "worktree_directory": "../acme-worktrees" } } Defensive patterns
Strategy: validation
Validate before calling
// Mirror Zed's containment rule before creating worktrees programmatically
let joined = repository_anchor_path.join(trimmed_setting);
let resolved = normalize_path(joined);
let parent = repository_anchor_path.parent().unwrap_or(repository_anchor_path);
if !resolved.starts_with(parent) {
return Err("worktree directory escapes the repository root and its parent".into());
} Prevention
- 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
When it happens
Trigger: git.worktree_directory containing enough '..' segments to resolve above the repository's parent directory, for example "../.." or "subdir/../../..", when a worktree is created.
Common situations: Trying to gather all worktrees in a central folder like ~/worktrees; deeply nested repositories where "../.." looks harmless.
Related errors
- git.worktree_directory must be a relative path, got: {worktr
- git.worktree_directory must not be empty
- git.worktree_directory must not be ".." (use "../some-name"
- untracked files are present and will NOT be included in the
- A worktree already exists at {}
AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20).
Data as JSON: /api/errors/c4117ac30198d3b2.
Report an issue: GitHub.