{"record":{"id":"e85ddcc2672cc386","repo":"zeroclaw-labs/zeroclaw","slug":"path-path-is-a-broad-system-root-set-allow-br","errorCode":null,"errorMessage":"path '{path}' is a broad system root; set allow_broad_roots = true to watch it","messagePattern":"path '(.+?)' is a broad system root; set allow_broad_roots = true to watch it","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-config/src/schema.rs","lineNumber":16428,"sourceCode":"        }\n    }\n}\n\nconst FILESYSTEM_BROAD_ROOTS: [&str; 8] = [\n    \"/\", \"/home\", \"/etc\", \"/var\", \"/proc\", \"/sys\", \"/dev\", \"/tmp\",\n];\n\nimpl FilesystemConfig {\n    /// Validate the filesystem listener configuration.\n    pub fn validate(&self) -> anyhow::Result<()> {\n        if self.paths.is_empty() {\n            anyhow::bail!(\"at least one path must be configured\");\n        }\n        for path in &self.paths {\n            let trimmed = path.trim_end_matches('/');\n            let normalized = if trimmed.is_empty() { \"/\" } else { trimmed };\n            if !self.allow_broad_roots && FILESYSTEM_BROAD_ROOTS.contains(&normalized) {\n                anyhow::bail!(\n                    \"path '{path}' is a broad system root; set allow_broad_roots = true to watch it\"\n                );\n            }\n        }\n        for kind in &self.events {\n            if !matches!(\n                kind.as_str(),\n                \"created\" | \"modified\" | \"deleted\" | \"renamed\"\n            ) {\n                anyhow::bail!(\n                    \"event '{kind}' is invalid; expected created, modified, deleted, or renamed\"\n                );\n            }\n        }\n        Ok(())\n    }\n}\n","sourceCodeStart":16410,"sourceCodeEnd":16446,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-config/src/schema.rs#L16410-L16446","documentation":"`FilesystemConfig` denies watching broad system roots (`/`, `/home`, `/etc`, `/var`, `/proc`, `/sys`, `/dev`, `/tmp`) unless `allow_broad_roots = true`. Trailing slashes are normalized before the check, so `/home/` still matches. The guard exists because pseudo-filesystems like `/proc` and `/sys` flood the watcher with kernel-object events and can leak system paths into SOP payloads.","triggerScenarios":"`paths = [\"/tmp\"]` or `paths = [\"/\"]` with `allow_broad_roots` unset (defaults false); `paths = [\"/home/\"]` (trailing slash trimmed, still denied); pasting a log-watching example that tails `/var`.","commonSituations":"Quick experiments that watch `/tmp` for scratch files; assuming `/home` is fine because it only contains user data; migrating from a simple inotify script that watched `/` without issues on tiny systems.","solutions":["Narrow the path below the broad root, e.g. `/tmp/zeroclaw-watch` or `/home/user/project`.","If you truly need the broad root, set `allow_broad_roots = true` and accept the event-volume and payload-exposure risk, ideally pairing it with include/exclude filters.","For `/proc` and `/sys` specifically, prefer a targeted path or a different mechanism — they are near-unwatchable at volume."],"exampleFix":"# before\npaths = [\"/tmp\"]\n\n# after\npaths = [\"/tmp/zeroclaw-watch\"]","handlingStrategy":"validation","validationCode":"const BROAD: [&str; 8] = [\"/\", \"/home\", \"/etc\", \"/var\", \"/proc\", \"/sys\", \"/dev\", \"/tmp\"];\nlet norm = |p: &str| {\n    let t = p.trim_end_matches('/');\n    if t.is_empty() { \"/\" } else { t }\n};\nanyhow::ensure!(\n    cfg.allow_broad_roots || cfg.paths.iter().all(|p| !BROAD.contains(&norm(p))),\n    \"broad root watch requires allow_broad_roots = true\"\n);","typeGuard":"fn is_broad_root(path: &str) -> bool {\n    let t = path.trim_end_matches('/');\n    let n = if t.is_empty() { \"/\" } else { t };\n    [\"/\", \"/home\", \"/etc\", \"/var\", \"/proc\", \"/sys\", \"/dev\", \"/tmp\"].contains(&n)\n}","tryCatchPattern":null,"preventionTips":["Default to the narrowest directory that covers the need.","Treat allow_broad_roots = true as a deliberate, reviewed decision — pair it with include/exclude filters.","Remember trailing slashes are normalized: /tmp/ is still /tmp."],"tags":["filesystem","config","watch-paths","safety-guard","zeroclaw"],"backgroundTag":"filesystem-watch-path-denied","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}