zed-industries/zed · error

`cd` directory {cd:?} was not in any root directory in the p

Error message

`cd` directory {cd:?} was not in any root directory in the project.

What it means

For any non-trivial cd value, the terminal tool resolves it to a directory inside a worktree: it matches worktree root names and absolute paths, both lexically normalized and classified with the project's PathStyle (not the host's, so POSIX paths work from Windows hosts driving WSL/SSH projects). If no worktree matches, the command is rejected before a shell is spawned. Single-file worktrees are skipped because a file cannot be a working directory.

Source

Thrown at crates/agent/src/tools/terminal_tool.rs:1373

            None => Ok(None),
        }
    } else {
        let path_style = project.path_style(cx);
        let worktree_roots = project
            .worktrees(cx)
            .filter_map(|worktree| {
                let worktree = worktree.read(cx);
                // Skip single-file worktrees: a file can't be a working directory.
                let root_dir = worktree.root_dir()?;
                Some((worktree.root_name_str(), root_dir.to_path_buf()))
            })
            .collect::<Vec<_>>();

        if let Some(dir) = resolve_cd_in_worktrees(cd, path_style, &worktree_roots) {
            return Ok(Some(dir));
        }

        anyhow::bail!("`cd` directory {cd:?} was not in any root directory in the project.");
    }
}

/// Resolves a `cd` argument to an absolute worktree directory. `cd` may be a
/// worktree's root name or an absolute path to a worktree or a subdirectory
/// therein.
///
/// Absolute paths are classified with the project's [`PathStyle`] rather than
/// the host's, so an absolute POSIX path resolves correctly on a Windows host
/// driving a WSL/SSH project (#60040).
///
/// Both `cd` and the worktree roots are lexically normalized before prefix
/// matching. This resolves `.` and `..` components up front, so a path that
/// escapes a worktree does not have that worktree's root as a prefix and is
/// rejected (#60014). On Windows-style projects it also unifies `/` and `\`
/// separators, since models frequently write `C:/foo/bar` for a root stored
/// as `C:\foo\bar`.
fn resolve_cd_in_worktrees(

View on GitHub (pinned to bc538def45)

Solutions

  1. Use an absolute path that lies inside one of the project's worktree roots
  2. Add the target folder to the project (Add Folder to Project) so it becomes a worktree, then retry
  3. Use the exact root name as displayed in the project panel

Example fix

// before — target outside every worktree
run_terminal_command(command="ls", cd="/tmp/work")

// after — add /tmp/work as a project folder, or cd inside an existing root
run_terminal_command(command="ls", cd="/home/me/repo/scripts")
Defensive patterns

Strategy: validation

Validate before calling

let roots: Vec<(String, PathBuf)> = project
    .read(cx)
    .worktrees(cx)
    .filter_map(|worktree| {
        let worktree = worktree.read(cx);
        Some((worktree.root_name_str().to_string(), worktree.root_dir()?.to_path_buf()))
    })
    .collect();
let resolves = cd == "."
    || roots.iter().any(|(name, root)| cd == *name || root.join(&cd).starts_with(root));
if !resolves {
    // cd will be rejected; pick a directory inside a worktree root
}

Try / catch

On the 'not in any root directory' message, list the project's worktree roots back to the caller and request a corrected cd.

Prevention

When it happens

Trigger: cd is neither a worktree root name nor a path under any worktree root: outside paths like /tmp or ~/.config, a typo in the root name, or any path into a single-file worktree (its root_dir() is None so it never participates).

Common situations: The agent suggests cd-ing to a scratch directory outside the project; the project was opened as a single file; a stale absolute path from another machine.

Related errors


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