{"record":{"id":"3aca45a7e6e3688d","repo":"zed-industries/zed","slug":"cannot-list-directory-because-its-path-matches-the-3aca45","errorCode":null,"errorMessage":"Cannot list directory because its path matches the user's worktree `private_paths` setting: {}","messagePattern":"Cannot list directory because its path matches the user's worktree `private_paths` setting: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/agent/src/tools/list_directory_tool.rs","lineNumber":300,"sourceCode":"                }\n\n                if global_settings.is_path_private(&project_path.path) {\n                    anyhow::bail!(\n                        \"Cannot list directory because its path matches the user's global `private_files` setting: {}\",\n                        input.path\n                    );\n                }\n\n                let worktree_settings = WorktreeSettings::get(Some((&project_path).into()), cx);\n                if worktree_settings.is_path_excluded(&project_path.path) {\n                    anyhow::bail!(\n                        \"Cannot list directory because its path matches the user's worktree `file_scan_exclusions` setting: {}\",\n                        input.path\n                    );\n                }\n\n                if worktree_settings.is_path_private(&project_path.path) {\n                    anyhow::bail!(\n                        \"Cannot list directory because its path matches the user's worktree `private_paths` setting: {}\",\n                        input.path\n                    );\n                }\n\n                let worktree_snapshot = worktree.read(cx).snapshot();\n                let Some(entry) = worktree_snapshot.entry_for_path(&project_path.path) else {\n                    anyhow::bail!(\"Path not found: {}\", input.path);\n                };\n                if !entry.is_dir() {\n                    anyhow::bail!(\"{} is not a directory.\", input.path);\n                }\n\n                anyhow::Ok(())\n            }).map_err(|e| e.to_string())?;\n\n            if let Some(canonical_target) = &symlink_canonical_target {\n                let authorize = cx.update(|cx| {","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/agent/src/tools/list_directory_tool.rs#L282-L318","documentation":"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.","triggerScenarios":"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`.","commonSituations":"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.","solutions":["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.","Keep the path private and instruct the agent/model to avoid it; retrying with a different phrasing will not bypass the check.","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.","Point the agent at a sanitized copy of the directory outside the matched pattern."],"exampleFix":"// .zed/settings.json (worktree settings)\n// before\n{\n  \"private_paths\": [\"secrets\"]\n}\n// after — only the key material is private, the directory itself listable\n{\n  \"private_paths\": [\"secrets/*.key\"]\n}","handlingStrategy":"validation","validationCode":"let worktree = WorktreeSettings::get(Some((&project_path).into()), cx);\nif worktree.is_path_private(&project_path.path) {\n    // do not call list_directory on this path; it is private by policy\n}","typeGuard":null,"tryCatchPattern":"match list_directory(path).await {\n    Err(e) if e.to_string().contains(\"private_paths\") => {\n        // privacy boundary hit — stop, never retry with variations\n    }\n    rest => rest,\n}","preventionTips":["Scope `private_paths` to specific secret files/dirs, not whole trees the agent may need to navigate.","Treat these refusals as expected behavior in agent loop code; filter such paths out of planned tool calls.","Keep secrets outside the worktree so exclusions and agent needs never collide."],"tags":["rust","zed","agent","list-directory","settings","private-paths","privacy","access-denied"],"backgroundTag":"file-access-denied-by-settings","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}