BerriAI/litellm · error · ValueError
Cisco AI Defense guardrail: invalid rule definition: {rule!r
Error message
Cisco AI Defense guardrail: invalid rule definition: {rule!r} What it means
ValueError raised while normalizing the Cisco AI Defense guardrail's rules config (_normalize_rules-style path): a rules entry was neither a plain string (shorthand for a rule name) nor a mapping the normalizer could extract a rule_name from. The offending value is echoed with {rule!r}, so the config mistake is directly visible. This is a config-shape validation error raised at guardrail init time.
Source
Thrown at litellm/proxy/guardrails/guardrail_hooks/cisco_ai_defense/cisco_ai_defense.py:940
rule = dumped
if isinstance(rule, dict):
normalized: Final[dict[str, object]] = {}
rule_name: Final = rule.get("rule_name")
if rule_name:
normalized["rule_name"] = rule_name
entity_types: Final = rule.get("entity_types")
if entity_types:
normalized["entity_types"] = list(entity_types)
rule_id: Final = rule.get("rule_id")
if rule_id is not None:
normalized["rule_id"] = rule_id
classification: Final = rule.get("classification")
if classification:
normalized["classification"] = classification
return normalized
raise ValueError(f"Cisco AI Defense guardrail: invalid rule definition: {rule!r}")
# ------------------------------------------------------------------
# Response processing
# ------------------------------------------------------------------
def _finalize_inspection(
self,
inspect_response: dict[str, Any],
request_data: dict,
context: _ScanContext,
start_time: datetime,
response_obj: object = None,
) -> dict[str, object]:
"""Parse, log, and (optionally) raise/redact on the Cisco verdict.
``context.direction`` is ``"input"`` for request scans and ``"output"``
for response scans (used for metadata namespacing and response headers).
``response_obj`` is the LiteLLM response object (or MCP tool-callView on GitHub (pinned to 77b7c6c40c)
Solutions
- Check the echoed {rule!r} in the error — it shows exactly which entry is invalid.
- Make each rules entry either a plain string ("rule-name") or a dict with recognized keys: rule_name (or shorthand), entity_types (list), rule_id, classification.
- Validate the config with a YAML/JSON schema check before deploying; reload the proxy after fixing.
Example fix
# before — entry has unrecognized keys only
litellm_params:
guardrail: cisco_ai_defense
rules:
- rulename: prompt_injection
# after
litellm_params:
guardrail: cisco_ai_defense
rules:
- rule_name: prompt_injection
entity_types: [PROMPT_INJECTION] Defensive patterns
Strategy: type-guard
Validate before calling
def normalize_rule(r):
if isinstance(r, str) and r.strip():
return {"rule_name": r}
if isinstance(r, dict) and (r.get("rule_name") or any(k in r for k in ("entity_types", "rule_id", "classification"))):
out = {k: v for k, v in r.items() if k in ("rule_name", "entity_types", "rule_id", "classification")}
if "rule_name" not in out:
out["rule_name"] = r.get("rule_name") or r.get("name")
return out
raise ValueError(f"invalid cisco rule definition: {r!r}")
rules = [normalize_rule(r) for r in config_rules] # run before writing config Type guard
from typing import Any
def is_valid_cisco_rule(rule: Any) -> bool:
if isinstance(rule, str):
return bool(rule.strip())
return (isinstance(rule, dict)
and isinstance(rule.get("rule_name"), str)
and ("entity_types" not in rule or isinstance(rule["entity_types"], list))) Prevention
- Validate the rules block in CI with the same shape rules the guardrail enforces (string OR dict with rule_name/entity_types/rule_id/classification).
- Generate config from typed data (pydantic model) rather than hand-written YAML for rule lists.
- Unit-test guardrail config against a schema test that mirrors _normalize_rules behavior.
When it happens
Trigger: Passing rules: [123, null, [], {"name": ...}] — i.e., entries that are not strings and not dicts carrying the recognized keys (rule_name via shorthand, entity_types, rule_id, classification). Also strings that aren't matched and dicts missing every recognized field fall through to this raise.
Common situations: Converting a rules config from another format (YAML anchors producing None, JSON numbers), typos like {"rulename": "x"} instead of rule_name, or copy-pasting Cisco console JSON where rule entries are nested one level deeper than expected.
Understand the failure class
Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.
Related errors
- Cisco AI Defense API key is required. Set `CISCO_AI_DEFENSE_
- max_bytes_per_call must be >= 0 (0 disables the cap; positiv
- Event hook {hook} is not in the supported event hooks {suppo
- Event hook {event_hook} is not in the supported event hooks
- RSS feed missing <channel> element
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/70d5eeb3903d91ce.
Report an issue: GitHub.