zed-industries/zed · error · anyhow::Error
`cd` directory was not in any root directory in the project.
Error message
`cd` directory {cd:?} was not in any root directory in the project. What it means
When an agent terminal command includes `cd <dir>`, the terminal tool collects every worktree's `(root_name, root_dir)` (skipping single-file worktrees, since a file cannot be a cwd) and calls `resolve_cd_in_worktrees`. If the `cd` target is neither a worktree root name nor an absolute path under any root, it bails with this message. Absolute paths are classified with the project's `PathStyle`, not the host's, so a Windows host can target WSL/SSH POSIX paths — but they must still be inside a root.
Solutions
- Only `cd` to paths inside a currently open worktree, or to a worktree's root name.
- Open the additional folder in the Zed project (multi-root) so its root becomes resolvable.
- Use relative paths within the already-correct cwd instead of `cd`-ing out.
- For remote/WSL projects, use the project's POSIX-style absolute path, not the host's path.
Example fix
# agent terminal command # before cd /home/user/other-project && cargo test # outside any root -> error # after (open other-project as a second worktree first) cd other-project && cargo test # root name resolves
Defensive patterns
Strategy: validation
Validate before calling
// Before emitting a cd, verify the target is a root name or under a root dir:
let roots: Vec<(String, PathBuf)> = project.worktrees(cx).iter().filter_map(|wt| {
let wt = wt.read(cx);
Some((wt.root_name_str().to_string(), wt.root_dir()?.to_path_buf()))
}).collect();
let ok = roots.iter().any(|(name, dir)| cd == *name
|| normalize(&resolve(cd)).starts_with(dir));
if !ok { /* rewrite the command to stay inside a worktree */ } Type guard
fn cd_resolves(cd: &str, roots: &[(String, PathBuf)]) -> bool {
roots.iter().any(|(name, dir)| {
cd == name || Path::new(cd).normalize().starts_with(dir)
})
} Try / catch
match run_terminal(cmd).await {
Err(e) if e.to_string().contains("was not in any root directory") => {
// re-issue without the cd, or open the folder as a worktree first
}
rest => rest,
} Prevention
- Give the agent the correct worktree root name instead of out-of-project absolute paths.
- Open all needed folders as multi-root worktrees before driving the terminal.
- Remember single-file worktrees cannot serve as cwd roots.
When it happens
Trigger: The model emits `cd /some/path/outside/the/project`, `cd ../sibling-repo`, or `cd <name>` where `<name>` is not any worktree root name; also when every open worktree is a single file so the roots list is empty.
Common situations: The agent assumes a broader filesystem than the project allows; the user has one folder open but asks the agent to work in another; monorepo subdirectories are fine but sibling repos are not.
Related errors
- auto_compact threshold of 0 is not valid
- Cannot list directory because its path matches the user's…
- Cannot list directory because its path matches the user's…
- Cannot read file because its path matches the global…
- Cannot read file because its path matches the global…
AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20).
Data as JSON: /api/errors/e6785561b1084fe9.
Report an issue: GitHub.
Appendix: 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 f4178619ac)