{"record":{"id":"95b0a9dba661cefc","repo":"zeroclaw-labs/zeroclaw","slug":"invalid-memory-policy-threat-scan-value-other","errorCode":null,"errorMessage":"invalid memory.policy.threat_scan value {other:?}; expected off, on, or strict","messagePattern":"invalid memory\\.policy\\.threat_scan value (.+?); expected off, on, or strict","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-memory/src/scanned.rs","lineNumber":89,"sourceCode":"    fn alias(&self) -> &str {\n        self.inner.alias()\n    }\n}\n\nimpl<M: Memory> ScannedMemory<M> {\n    pub fn new(inner: M, policy: &MemoryPolicyConfig) -> Self {\n        Self {\n            inner,\n            policy: policy.clone(),\n        }\n    }\n\n    fn scan_mode(&self) -> anyhow::Result<ThreatScanMode> {\n        match self.policy.threat_scan.trim().to_ascii_lowercase().as_str() {\n            \"off\" => Ok(ThreatScanMode::Off),\n            \"on\" => Ok(ThreatScanMode::On),\n            \"strict\" => Ok(ThreatScanMode::Strict),\n            other => anyhow::bail!(\n                \"invalid memory.policy.threat_scan value {other:?}; expected off, on, or strict\"\n            ),\n        }\n    }\n\n    fn on_hit(&self) -> anyhow::Result<OnHit> {\n        match self\n            .policy\n            .threat_scan_on_hit\n            .trim()\n            .to_ascii_lowercase()\n            .as_str()\n        {\n            \"reject\" => Ok(OnHit::Reject),\n            \"block-on-read\" | \"block_on_read\" => Ok(OnHit::BlockOnRead),\n            other => anyhow::bail!(\n                \"invalid memory.policy.threat_scan_on_hit value {other:?}; expected reject or block-on-read\"\n            ),","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-memory/src/scanned.rs#L71-L107","documentation":"ScannedMemory::scan_mode() parses [memory.policy].threat_scan: trimmed, lowercased, then matched against exactly off | on | strict; anything else bails. The value is parsed lazily inside store/recall paths, so a typo survives config load and detonates on the first scanned memory operation.","triggerScenarios":"Setting threat_scan = \"enabled\", \"true\", \"false\", or \"strict mode\" in zeroclaw.toml; case is fine (\"Strict\" works because of lowercasing) but extra words and punctuation are not.","commonSituations":"Copy-pasted config snippets from other zeroclaw versions; booleans where the enum is expected; docs drift on policy field values.","solutions":["Set threat_scan to exactly one of: off, on, strict","Restart the agent after editing [memory.policy]","Confirm the effective value via the loaded-config view before the first write","Add a startup validation pass over enum-like policy fields"],"exampleFix":"# before\n[memory.policy]\nthreat_scan = \"enabled\"\n\n# after\n[memory.policy]\nthreat_scan = \"on\"   # off | on | strict","handlingStrategy":"validation","validationCode":"const VALID: [&str; 3] = [\"off\", \"on\", \"strict\"];\nlet v = cfg.memory.policy.threat_scan.trim().to_ascii_lowercase();\nanyhow::ensure!(VALID.contains(&v.as_str()), \"threat_scan must be off|on|strict, got {v}\");","typeGuard":"fn is_valid_threat_scan(v: &str) -> bool {\n    matches!(v.trim().to_ascii_lowercase().as_str(), \"off\" | \"on\" | \"strict\")\n}","tryCatchPattern":"if let Err(e) = memory.store(k, v).await {\n    if e.to_string().contains(\"invalid memory.policy.threat_scan value\") { fix_config_and_restart(); }\n    return Err(e);\n}","preventionTips":["Validate enum-like policy fields at startup, not on first write","Pin policy values from docs, not memory","Add config lint/CI checks for [memory.policy]"],"tags":["configuration","policy","threat-scan","validation","rust"],"backgroundTag":"invalid-config-value","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}