zed-industries/zed · error
{input_path} is not a directory.
Error message
{input_path} is not a directory. What it means
The path exists in the worktree snapshot but is a file, not a directory: `entry.is_dir()` is false. The list-directory tool only enumerates directories, so the call fails with this message naming the input path. Nothing is listed and no filesystem access happens beyond the lookup.
Source
Thrown at crates/agent/src/tools/list_directory_tool.rs:131
input_path: &str,
cx: &App,
) -> Result<String> {
let worktree = project
.read(cx)
.worktree_for_id(project_path.worktree_id, cx)
.with_context(|| format!("{input_path} is not in a known worktree"))?;
let global_settings = WorktreeSettings::get_global(cx);
let worktree_settings = WorktreeSettings::get(Some(project_path.into()), cx);
let worktree_snapshot = worktree.read(cx).snapshot();
let worktree_root_name = worktree.read(cx).root_name();
let Some(entry) = worktree_snapshot.entry_for_path(&project_path.path) else {
return Err(anyhow!("Path not found: {}", input_path));
};
if !entry.is_dir() {
return Err(anyhow!("{input_path} is not a directory."));
}
let mut folders = Vec::new();
let mut files = Vec::new();
for entry in worktree_snapshot.child_entries(&project_path.path) {
// Skip private and excluded files and directories
if global_settings.is_path_private(&entry.path)
|| global_settings.is_path_excluded(&entry.path)
{
continue;
}
let project_path: ProjectPath = (worktree_snapshot.id(), entry.path.clone()).into();
if worktree_settings.is_path_excluded(&project_path.path)
|| worktree_settings.is_path_private(&project_path.path)
{
continue;View on GitHub (pinned to bc538def45)
Solutions
- Pass the parent directory instead: `src/main.rs` → `src`.
- Use the read-file tool when the target is a file.
- Strip trailing file components from model-provided paths before invoking the tool.
Example fix
# before
list_directory("Cargo.toml") # '<input> is not a directory.'
# after
list_directory(".") # or: read_file("Cargo.toml") Defensive patterns
Strategy: validation
Validate before calling
let Some(entry) = worktree_snapshot.entry_for_path(&project_path.path) else {
anyhow::bail!("path not found: {input_path}");
};
if !entry.is_dir() {
anyhow::bail!("{input_path} is a file — pass its parent directory");
} Type guard
fn is_directory_in_worktree(
snapshot: &WorktreeSnapshot,
project_path: &ProjectPath,
) -> bool {
snapshot
.entry_for_path(&project_path.path)
.map(|entry| entry.is_dir())
.unwrap_or(false)
} Prevention
- Route file reads to the read-file tool; list only directories.
- Trim trailing file components from model-provided paths before invoking list-directory.
- State input expectations (directory, not file) clearly in the tool description.
When it happens
Trigger: Passing a file path (e.g. `Cargo.toml`, `src/main.rs`) to the list-directory tool instead of a directory.
Common situations: The model confusing the list-directory and read-file tools; paths whose final component is a file (`src/lib.rs` instead of `src`); trailing-component mistakes after path manipulation.
Related errors
- Invalid glob: {err}
- Path not found: {}
- {error_message}
- Unexpected response structure: ${JSON.stringify(data)}
- unknown benchmark '{benchmark_id}' (valid: {valid})
AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16).
Data as JSON: /api/errors/acbb4a1522dda373.
Report an issue: GitHub.