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

  1. Keep worktrees inside the repository: "tools/worktrees" or ".worktrees"
  2. Keep them directly beside the repository: "../<repo-name>-worktrees"
  3. 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

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


AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20). Data as JSON: /api/errors/c4117ac30198d3b2. Report an issue: GitHub.