unicity-aos/aos-ce · warning

policy_rules failed to parse

Error message

policy_rules failed to parse: {e}

What it means

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.

Solutions

  1. Validate the variable content with `echo "$POLICY_RULES" | python3 -m json.tool` (or jq) and fix the JSON syntax per the serde error message.
  2. 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).
  3. If the value is large, load it from a file instead of an env var to avoid shell escaping issues.
  4. Check for shell quoting problems: use single quotes around the JSON and avoid interpolation.

Example fix

// before
export POLICY_RULES="{'deny': ['fs_write']}"  // not JSON, single quotes
// after
export POLICY_RULES='[{"action":"deny","tool":"fs_write"}]'
Defensive patterns

Strategy: validation

Validate before calling

# Validate policy JSON before deploying
printf '%s' "$POLICY_RULES" | jq -e 'type == "array" and length > 0' \
  || { echo "POLICY_RULES must be a non-empty JSON array of rules"; exit 1; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13). Data as JSON: /api/errors/9a8d5c24bf13b3e2. Report an issue: GitHub.

Appendix: source

Thrown at crates/aos-mcp-broker/src/policy.rs:276

pub(crate) fn load_rules() -> Vec<Rule> {
    let raw = match env::var_opt(POLICY_RULES_ENV) {
        Ok(Some(s)) if !s.trim().is_empty() => s,
        Ok(_) => return Vec::new(),
        Err(e) => {
            audit_load_failure("env_read_error");
            log::warn(format!(
                "{}: policy_rules env read failed: {e:?}",
                crate::profile::log_tag()
            ));
            return Vec::new();
        }
    };

    let parsed: Vec<Rule> = match serde_json::from_str(&raw) {
        Ok(rules) => rules,
        Err(e) => {
            audit_load_failure("parse_error");
            log::warn(format!(
                "{}: policy_rules failed to parse: {e}",
                crate::profile::log_tag()
            ));
            return Vec::new();
        }
    };

    if let Err(reason) = validate(&parsed) {
        audit_load_failure(reason);
        log::warn(format!(
            "{}: policy_rules rejected ({reason}); policy NOT in force",
            crate::profile::log_tag()
        ));
        return Vec::new();
    }
    parsed
}

View on GitHub (pinned to f6f22024fb)