zed-industries/zed · error

Cannot list directory because its path matches the user's…

Error message

Cannot list directory because its path matches the user's worktree `private_paths` setting: {}

What it means

Zed's agent `list_directory` tool refuses to enumerate a directory whose path matches the worktree-level `private_paths` setting. Private paths are a stronger restriction than scan exclusions: they exist purely to keep contents (even path names) away from the model, so listing is denied even though the files exist. It fires when `WorktreeSettings::get(...).is_path_private(&project_path.path)` returns true, after the worktree `file_scan_exclusions` check.

Solutions

  1. If access is genuinely required, remove the path from `private_paths` in the worktree `.zed/settings.json` — but prefer moving secrets out of the project instead.
  2. Keep the path private and instruct the agent/model to avoid it; retrying with a different phrasing will not bypass the check.
  3. Verify the path is not also matched by global `private_files` or `file_scan_exclusions`, since those checks run first and produce their own messages.
  4. Point the agent at a sanitized copy of the directory outside the matched pattern.

Example fix

// .zed/settings.json (worktree settings)
// before
{
  "private_paths": ["secrets"]
}
// after — only the key material is private, the directory itself listable
{
  "private_paths": ["secrets/*.key"]
}
Defensive patterns

Strategy: validation

Validate before calling

let worktree = WorktreeSettings::get(Some((&project_path).into()), cx);
if worktree.is_path_private(&project_path.path) {
    // do not call list_directory on this path; it is private by policy
}

Try / catch

match list_directory(path).await {
    Err(e) if e.to_string().contains("private_paths") => {
        // privacy boundary hit — stop, never retry with variations
    }
    rest => rest,
}

Prevention

When it happens

Trigger: The `list_directory` tool is called on a path matched by `private_paths` (or `private_files` glob patterns) in the project's `.zed/settings.json`, e.g. `.env`, `secrets/`, `*.pem`.

Common situations: Users add `.env`, SSH keys, or credential directories to `private_paths` to keep them out of agent context, then prompt the agent to inspect those directories. The error is the privacy boundary working as designed.

Related errors


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

Appendix: source

Thrown at crates/agent/src/tools/list_directory_tool.rs:300

                }

                if global_settings.is_path_private(&project_path.path) {
                    anyhow::bail!(
                        "Cannot list directory because its path matches the user's global `private_files` setting: {}",
                        input.path
                    );
                }

                let worktree_settings = WorktreeSettings::get(Some((&project_path).into()), cx);
                if worktree_settings.is_path_excluded(&project_path.path) {
                    anyhow::bail!(
                        "Cannot list directory because its path matches the user's worktree `file_scan_exclusions` setting: {}",
                        input.path
                    );
                }

                if worktree_settings.is_path_private(&project_path.path) {
                    anyhow::bail!(
                        "Cannot list directory because its path matches the user's worktree `private_paths` setting: {}",
                        input.path
                    );
                }

                let worktree_snapshot = worktree.read(cx).snapshot();
                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!("{} is not a directory.", input.path);
                }

                anyhow::Ok(())
            }).map_err(|e| e.to_string())?;

            if let Some(canonical_target) = &symlink_canonical_target {
                let authorize = cx.update(|cx| {

View on GitHub (pinned to f4178619ac)