{"record":{"id":"7aafc246f0eb72fe","repo":"BerriAI/litellm","slug":"cisco-ai-defense-surface-api-returned-http-stat","errorCode":null,"errorMessage":"Cisco AI Defense {surface} API returned HTTP {status_code}: {body_snippet}","messagePattern":"Cisco AI Defense (.+?) API returned HTTP (.+?): (.+?)","errorType":"exception","errorClass":"CiscoAIDefenseGuardrailAPIError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/guardrails/guardrail_hooks/cisco_ai_defense/cisco_ai_defense.py","lineNumber":830,"sourceCode":"                \"POST\",\n                url,\n                headers=headers,\n                json=payload,\n                timeout=self.timeout,\n            )\n            response: Final = await self.async_handler.client.send(\n                request,\n                follow_redirects=False,\n            )\n            response.raise_for_status()\n        except httpx.HTTPStatusError as exc:\n            status_code: Final = exc.response.status_code if exc.response is not None else 0\n            body_snippet = \"\"\n            try:\n                body_snippet = exc.response.text[:500] if exc.response else \"\"\n            except Exception:\n                body_snippet = \"\"\n            raise CiscoAIDefenseGuardrailAPIError(\n                f\"Cisco AI Defense {surface} API returned HTTP {status_code}: {body_snippet}\"\n            ) from exc\n        except httpx.TimeoutException as exc:\n            raise CiscoAIDefenseGuardrailAPIError(\n                f\"Cisco AI Defense {surface} API call timed out after {self.timeout}s\"\n            ) from exc\n        except httpx.RequestError as exc:\n            raise CiscoAIDefenseGuardrailAPIError(f\"Cisco AI Defense {surface} API request failed: {exc}\") from exc\n\n        try:\n            return response.json()\n        except ValueError as exc:\n            raise CiscoAIDefenseGuardrailAPIError(\n                f\"Cisco AI Defense {surface} API returned a non-JSON response\"\n            ) from exc\n\n    def _build_headers(self) -> dict[str, str]:\n        return {","sourceCodeStart":812,"sourceCodeEnd":848,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/guardrails/guardrail_hooks/cisco_ai_defense/cisco_ai_defense.py#L812-L848","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Verify connectivity manually: curl -H \"<CISCO_API_KEY_HEADER>: $KEY\" $CISCO_AI_DEFENSE_API_BASE/... and inspect the raw status.","Set fallback_on_error: allow in the guardrail config so unavailability lets traffic proceed unscanned (log-only) instead of erroring.","Contact Cisco support / check status page for sustained 5xx, and check tenant quotas for 429s."],"exampleFix":"# before — any Cisco 4xx/5xx fails the LLM call\nlitellm_params:\n  guardrail: cisco_ai_defense\n\n# after — degrade gracefully when Cisco returns errors\nlitellm_params:\n  guardrail: cisco_ai_defense\n  fallback_on_error: allow","handlingStrategy":"retry","validationCode":"import httpx, os\nbase = os.environ.get(\"CISCO_AI_DEFENSE_API_BASE\", \"https://api.ai-defense.cisco.com\")\ntry:\n    r = httpx.get(f\"{base}/\", headers={\"Authorization\": f\"Bearer {os.environ['CISCO_AI_DEFENSE_API_KEY']}\"}, timeout=5)\n    print(\"reachable, status\", r.status_code)\nexcept Exception as e:\n    print(\"cisco endpoint unreachable:\", e)","typeGuard":null,"tryCatchPattern":"from litellm.proxy.guardrails.guardrail_hooks.cisco_ai_defense import CiscoAIDefenseGuardrailAPIError\nimport time\nfor attempt in range(3):\n    try:\n        resp = litellm.completion(...)\n        break\n    except Exception as e:\n        if isinstance(getattr(e, \"__cause__\", None), __import__(\"httpx\").HTTPStatusError):\n            status = e.__cause__.response.status_code\n            if status in (429, 500, 502, 503) and attempt < 2:\n                time.sleep(2 ** attempt); continue\n        if \"returned HTTP 401\" in str(e) or \"returned HTTP 403\" in str(e):\n            rotate_cisco_key(); raise\n        raise","preventionTips":["Configure fallback_on_error: allow unless strict fail-closed is mandated.","Monitor the body snippet embedded in the error — it usually names the exact Cisco-side cause.","Keep the API key in an automated rotation flow and alert on 401 spikes.","Verify api_base reachability from the proxy network in a pre-deploy smoke test."],"tags":["litellm","guardrails","cisco-ai-defense","http-status-error","api"],"backgroundTag":"guardrail-api-failure","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}