{"record":{"id":"9a8d5c24bf13b3e2","repo":"unicity-aos/aos-ce","slug":"policy-rules-failed-to-parse-e","errorCode":null,"errorMessage":"policy_rules failed to parse: {e}","messagePattern":"policy_rules failed to parse: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/aos-mcp-broker/src/policy.rs","lineNumber":276,"sourceCode":"pub(crate) fn load_rules() -> Vec<Rule> {\n    let raw = match env::var_opt(POLICY_RULES_ENV) {\n        Ok(Some(s)) if !s.trim().is_empty() => s,\n        Ok(_) => return Vec::new(),\n        Err(e) => {\n            audit_load_failure(\"env_read_error\");\n            log::warn(format!(\n                \"{}: policy_rules env read failed: {e:?}\",\n                crate::profile::log_tag()\n            ));\n            return Vec::new();\n        }\n    };\n\n    let parsed: Vec<Rule> = match serde_json::from_str(&raw) {\n        Ok(rules) => rules,\n        Err(e) => {\n            audit_load_failure(\"parse_error\");\n            log::warn(format!(\n                \"{}: policy_rules failed to parse: {e}\",\n                crate::profile::log_tag()\n            ));\n            return Vec::new();\n        }\n    };\n\n    if let Err(reason) = validate(&parsed) {\n        audit_load_failure(reason);\n        log::warn(format!(\n            \"{}: policy_rules rejected ({reason}); policy NOT in force\",\n            crate::profile::log_tag()\n        ));\n        return Vec::new();\n    }\n    parsed\n}\n","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/unicity-aos/aos-ce/blob/f6f22024fb1e8d122f28a1b4a9f75aee448ae839/crates/aos-mcp-broker/src/policy.rs#L258-L294","documentation":"This warning is logged in `load_rules` when the policy_rules environment variable is set and non-empty but its content is not valid JSON matching Vec<Rule>. serde_json::from_str fails, the failure is audited as `parse_error`, and an empty rule list is returned — so the broker silently runs with no policy rules even though configuration was supplied.","triggerScenarios":"POLICY_RULES_ENV contains malformed JSON: trailing commas, single quotes, unquoted keys, a JSON object instead of an array, or Rule fields with wrong types/missing required fields.","commonSituations":"Hand-edited env var with typos; YAML or shell-formatted rules pasted instead of JSON; schema drift after a broker upgrade changed the Rule struct; quotes mangled by shell escaping or secret-manager templating.","solutions":["Validate the variable content with `echo \"$POLICY_RULES\" | python3 -m json.tool` (or jq) and fix the JSON syntax per the serde error message.","Ensure the value is a JSON ARRAY of Rule objects with exactly the fields the Rule struct expects (correct types, no unknown/missing required fields).","If the value is large, load it from a file instead of an env var to avoid shell escaping issues.","Check for shell quoting problems: use single quotes around the JSON and avoid interpolation."],"exampleFix":"// before\nexport POLICY_RULES=\"{'deny': ['fs_write']}\"  // not JSON, single quotes\n// after\nexport POLICY_RULES='[{\"action\":\"deny\",\"tool\":\"fs_write\"}]'","handlingStrategy":"validation","validationCode":"# Validate policy JSON before deploying\nprintf '%s' \"$POLICY_RULES\" | jq -e 'type == \"array\" and length > 0' \\\n  || { echo \"POLICY_RULES must be a non-empty JSON array of rules\"; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Lint the policy JSON with jq/serde in CI before it reaches the environment.","Use single-quoted heredocs or config files to avoid shell escaping corruption.","Remember the failure mode is silent empty-rule-set — monitor audit_load_failure('parse_error') events.","Write a schema test against the Rule struct and regenerate examples on struct changes."],"tags":["json","policy","config","parse-error"],"backgroundTag":"schema-validation-failed","analyzedSha":"f6f22024fb1e8d122f28a1b4a9f75aee448ae839","analyzedAt":"2026-09-13T03:04:44.565Z","contentChangedAt":"2026-09-13T03:04:44.565Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}