{"record":{"id":"dbd2bad1dd288690","repo":"zeroclaw-labs/zeroclaw","slug":"at-least-one-path-must-be-configured","errorCode":null,"errorMessage":"at least one path must be configured","messagePattern":"at least one path must be configured","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-config/src/schema.rs","lineNumber":16422,"sourceCode":"            settle_ms: default_filesystem_settle_ms(),\n            read_content: false,\n            follow_symlinks: false,\n            max_content_bytes: default_filesystem_max_content_bytes(),\n            allow_broad_roots: false,\n            excluded_tools: Vec::new(),\n        }\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                );","sourceCodeStart":16404,"sourceCodeEnd":16440,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-config/src/schema.rs#L16404-L16440","documentation":"The filesystem SOP listener watches a list of directory paths and lifts create/modify/delete/rename events into the SOP engine. `FilesystemConfig::validate` requires at least one path because a watcher with an empty `paths` list (the serde default) would register nothing and the enabled channel would be a silent no-op.","triggerScenarios":"`[channels.filesystem.<alias>]` with `enabled = true` but no `paths` key; `paths = []` written explicitly; paths moved to another key by mistake during config refactors.","commonSituations":"Enabling the channel from a template before choosing watch directories; YAML/TOML indentation mistakes that leave `paths` under the wrong table so it parses as unset.","solutions":["Add at least one absolute directory path, e.g. `paths = [\"/var/lib/zeroclaw/inbox\"]`.","Prefer the narrowest directory that covers the events you need.","If the path is a broad system root, see the separate broad-root validation before enabling `allow_broad_roots`."],"exampleFix":"# before\n[channels.filesystem.watch]\nenabled = true\n# no paths\n\n# after\n[channels.filesystem.watch]\nenabled = true\npaths = [\"/var/lib/zeroclaw/inbox\"]","handlingStrategy":"validation","validationCode":"anyhow::ensure!(\n    !fs_cfg.paths.is_empty(),\n    \"channels.fileswatch alias needs at least one path\"\n);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set paths at the same time you flip enabled = true.","Prefer narrow, purpose-built directories over broad trees.","Watch TOML indentation so paths lands inside the right table."],"tags":["filesystem","config","required-field","zeroclaw"],"backgroundTag":"missing-required-config-field","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}