{"record":{"id":"01c56d10cc22c18f","repo":"unicity-aos/aos-ce","slug":"policy-rules-env-read-failed-e","errorCode":null,"errorMessage":"policy_rules env read failed: {e:?}","messagePattern":"policy_rules env read failed: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/aos-mcp-broker/src/policy.rs","lineNumber":264,"sourceCode":"/// Load the invoking principal's rule set from the `policy_rules` `[env]`\n/// value. Returns an EMPTY rule set (→ default allow → capability PEP is\n/// the live boundary) on any of: unset/empty value, host read error,\n/// JSON parse error, or a cap/shape violation — and emits a LOUD audit on\n/// the failure paths so an operator monitoring `astrid.v1.audit.policy_*`\n/// sees that policy is not in force.\n///\n/// This degrades to the capability PEP rather than failing CLOSED\n/// (deny-all) on a config error, so a malformed rule blob or a transient\n/// KV hiccup cannot brick every session. A deployment that wants strict\n/// fail-closed on config error is a future hardening knob; the tradeoff\n/// is recorded here deliberately.\npub(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    };","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/unicity-aos/aos-ce/blob/f6f22024fb1e8d122f28a1b4a9f75aee448ae839/crates/aos-mcp-broker/src/policy.rs#L246-L282","documentation":"This warning is emitted in `load_rules` when reading the POLICY_RULES_ENV environment variable itself fails (env::var_opt returns Err, e.g. a non-UTF-8 value or OS-level error). The loader audits the failure as `env_read_error` and returns an empty rule set, meaning the broker runs with NO policy rules (default-allow/empty policy) rather than crashing.","triggerScenarios":"Calling load_rules() when the policy_rules environment variable contains invalid Unicode (env var set to non-UTF8 bytes) or the OS call to read the environ fails.","commonSituations":"An env var injected by a container/orchestrator containing raw bytes that are not valid UTF-8; env size limits; process environment corruption; setting the variable via a shell with binary content.","solutions":["Check how POLICY_RULES_ENV is set; unset and re-set it with valid UTF-8 JSON content.","Inspect the value with `env | grep policy_rules` or `locale`-aware tools; replace binary/invalid bytes.","If you intend no rules, unset the variable entirely so load_rules takes the Ok(None)/empty path.","Verify the process supervisor (Docker, systemd, k8s) is not injecting malformed values for this key."],"exampleFix":"// before (invalid UTF-8 bytes injected)\nexport POLICY_RULES=$(cat rules.bin)\n// after\nexport POLICY_RULES=\"$(cat rules.json)\"  # ensure valid UTF-8 JSON","handlingStrategy":"validation","validationCode":"# Validate the env var is readable UTF-8 before launching the broker\ncase \"$POLICY_RULES\" in\n  '') echo \"policy_rules unset/empty (no rules)\" ;;\n  *)  printf '%s' \"$POLICY_RULES\" | iconv -f utf-8 -t utf-8 >/dev/null \\\n        || echo \"POLICY_RULES is not valid UTF-8\" ;;\nesac","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set config via files or validated config management rather than raw shell exports.","Validate env vars at process startup (fail fast) instead of at rule-load time.","Beware: empty rules means default policy — pair env-read failures with a loud audit/metric."],"tags":["environment","policy","config","fail-open"],"backgroundTag":"missing-env-var","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"}