BerriAI/litellm · error · CiscoAIDefenseGuardrailAPIError

Cisco AI Defense {surface} API returned HTTP {status_code}:

Error message

Cisco AI Defense {surface} API returned HTTP {status_code}: {body_snippet}

What it means

CiscoAIDefenseGuardrailAPIError wrapping an httpx.HTTPStatusError: the Cisco AI Defense inspection API returned a non-2xx status. The message includes the surface (request/response), the status code, and up to 500 bytes of the response body, so the upstream error (authentication problem, bad request payload, quota, or Cisco 5xx) is visible directly in the exception text.

Source

Thrown at litellm/proxy/guardrails/guardrail_hooks/cisco_ai_defense/cisco_ai_defense.py:830

                "POST",
                url,
                headers=headers,
                json=payload,
                timeout=self.timeout,
            )
            response: Final = await self.async_handler.client.send(
                request,
                follow_redirects=False,
            )
            response.raise_for_status()
        except httpx.HTTPStatusError as exc:
            status_code: Final = exc.response.status_code if exc.response is not None else 0
            body_snippet = ""
            try:
                body_snippet = exc.response.text[:500] if exc.response else ""
            except Exception:
                body_snippet = ""
            raise CiscoAIDefenseGuardrailAPIError(
                f"Cisco AI Defense {surface} API returned HTTP {status_code}: {body_snippet}"
            ) from exc
        except httpx.TimeoutException as exc:
            raise CiscoAIDefenseGuardrailAPIError(
                f"Cisco AI Defense {surface} API call timed out after {self.timeout}s"
            ) from exc
        except httpx.RequestError as exc:
            raise CiscoAIDefenseGuardrailAPIError(f"Cisco AI Defense {surface} API request failed: {exc}") from exc

        try:
            return response.json()
        except ValueError as exc:
            raise CiscoAIDefenseGuardrailAPIError(
                f"Cisco AI Defense {surface} API returned a non-JSON response"
            ) from exc

    def _build_headers(self) -> dict[str, str]:
        return {

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Read the embedded status/body: 401/403 → fix the API key; 404 → fix api_base; 400 → check inspection_type/metadata fields; 429/5xx → transient, retry or set fallback_on_error: allow.
  2. Verify connectivity manually: curl -H "<CISCO_API_KEY_HEADER>: $KEY" $CISCO_AI_DEFENSE_API_BASE/... and inspect the raw status.
  3. Set fallback_on_error: allow in the guardrail config so unavailability lets traffic proceed unscanned (log-only) instead of erroring.
  4. Contact Cisco support / check status page for sustained 5xx, and check tenant quotas for 429s.

Example fix

# before — any Cisco 4xx/5xx fails the LLM call
litellm_params:
  guardrail: cisco_ai_defense

# after — degrade gracefully when Cisco returns errors
litellm_params:
  guardrail: cisco_ai_defense
  fallback_on_error: allow
Defensive patterns

Strategy: retry

Validate before calling

import httpx, os
base = os.environ.get("CISCO_AI_DEFENSE_API_BASE", "https://api.ai-defense.cisco.com")
try:
    r = httpx.get(f"{base}/", headers={"Authorization": f"Bearer {os.environ['CISCO_AI_DEFENSE_API_KEY']}"}, timeout=5)
    print("reachable, status", r.status_code)
except Exception as e:
    print("cisco endpoint unreachable:", e)

Try / catch

from litellm.proxy.guardrails.guardrail_hooks.cisco_ai_defense import CiscoAIDefenseGuardrailAPIError
import time
for attempt in range(3):
    try:
        resp = litellm.completion(...)
        break
    except Exception as e:
        if isinstance(getattr(e, "__cause__", None), __import__("httpx").HTTPStatusError):
            status = e.__cause__.response.status_code
            if status in (429, 500, 502, 503) and attempt < 2:
                time.sleep(2 ** attempt); continue
        if "returned HTTP 401" in str(e) or "returned HTTP 403" in str(e):
            rotate_cisco_key(); raise
        raise

Prevention

When it happens

Trigger: Any _post inspection call that gets raise_for_status() failure: 401/403 for an invalid or expired API key, 400 for a malformed inspection payload (unsupported inspection_type or invalid metadata), 404 for a wrong CISCO_AI_DEFENSE_API_BASE (or a gateway path mismatch), 429 rate limiting, 5xx Cisco-side incidents.

Common situations: Rotated/expired Cisco keys after the proxy has been running; custom api_base pointing to a proxy that strips the auth header; api_base with a trailing path that 404s; burst traffic hitting Cisco tenant rate limits; non-JSON HTML error pages from corporate proxies producing confusing body snippets.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/7aafc246f0eb72fe. Report an issue: GitHub.