{"record":{"id":"6213677ee8c2c017","repo":"BerriAI/litellm","slug":"exc","errorCode":null,"errorMessage":"{exc}","messagePattern":"\\{exc\\}","errorType":"exception","errorClass":"GraySwanGuardrailAPIError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/guardrails/guardrail_hooks/grayswan/grayswan.py","lineNumber":253,"sourceCode":"                raise\n            end_time: Final = time.time()\n            status_code: Final = getattr(exc, \"status_code\", None) or getattr(exc, \"exception_status_code\", None)\n            self._log_guardrail_failure(\n                exc=exc,\n                request_data=request_data or {},\n                start_time=start_time,\n                end_time=end_time,\n                status_code=status_code,\n            )\n            if self.fail_open:\n                verbose_proxy_logger.warning(\n                    \"Gray Swan Guardrail: fail_open=True. Allowing request to proceed despite error: %s\",\n                    exc,\n                )\n                return inputs\n            if isinstance(exc, GraySwanGuardrailAPIError):\n                raise exc\n            raise GraySwanGuardrailAPIError(str(exc), status_code=status_code) from exc\n\n    def _is_grayswan_exception(self, exc: Exception) -> bool:\n        # Guardrail decision (passthrough) should always propagate,\n        # regardless of fail_open.\n        if isinstance(exc, ModifyResponseException):\n            return True\n        detail: Final = getattr(exc, \"detail\", None)\n        if isinstance(detail, dict):\n            return detail.get(\"error\") == GRAYSWAN_BLOCK_ERROR_MSG\n        return False\n\n    # ------------------------------------------------------------------\n    # Legacy Test Interface (for backward compatibility)\n    # ------------------------------------------------------------------\n\n    async def run_grayswan_guardrail(self, payload: dict) -> dict[str, Any]:\n        \"\"\"\n        Run the GraySwan guardrail on a payload.","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/guardrails/guardrail_hooks/grayswan/grayswan.py#L235-L271","documentation":"GraySwanGuardrailAPIError raised at the top of GraySwanGuardrail.apply_guardrail's exception handler when fail_open is False (it defaults to True) and the caught exception is not a guardrail decision (block/passthrough exceptions propagate via _is_grayswan_exception). It re-raises existing GraySwanGuardrailAPIError as-is, or wraps any other exception with its string form and a best-effort status_code. The guardrail failure is logged first via _log_guardrail_failure.","triggerScenarios":"fail_open explicitly set to false, and the monitor call fails — network error, timeout beyond guardrail_timeout (default 30s), non-2xx from raise_for_status, JSON decode failure; or any unexpected exception in response processing.","commonSituations":"Operators setting fail_open: false for strict compliance, then a GraySwan outage or timeout makes every request fail; oversized payloads timing out at the 30s default; auth failures after key rotation.","solutions":["Check the logged guardrail failure entry for the wrapped cause and status code.","Verify GRAYSWAN_API_KEY / GRAYSWAN_API_BASE and curl the monitor endpoint directly.","Raise guardrail_timeout if slow responses are the cause, or lower it to fail faster.","If availability matters more than strictness for this deployment, keep/set fail_open: true (default) so errors pass traffic through.","Remember block/passthrough decisions always propagate regardless of fail_open — only infrastructure errors are affected."],"exampleFix":"# before\nlitellm_params:\n  guardrail: grayswan\n  fail_open: false\n  guardrail_timeout: 30\n\n# after\nlitellm_params:\n  guardrail: grayswan\n  fail_open: false\n  guardrail_timeout: 60","handlingStrategy":"fallback","validationCode":"import os\nmissing = [v for v in ('GRAYSWAN_API_KEY',) if not os.getenv(v)]\nif missing:\n    raise SystemExit(f'deploy blocked, missing env: {missing}')","typeGuard":"from litellm.proxy.guardrails.guardrail_hooks.grayswan.grayswan import GraySwanGuardrailAPIError\n\ndef is_grayswan_api_error(exc: BaseException) -> bool:\n    return isinstance(exc, GraySwanGuardrailAPIError)","tryCatchPattern":"from litellm.proxy.guardrails.guardrail_hooks.grayswan.grayswan import GraySwanGuardrailAPIError\ntry:\n    result = await guardrail.apply_guardrail(inputs, request_data, input_type, logging_obj)\nexcept GraySwanGuardrailAPIError as e:\n    logger.warning('GraySwan API error, failing open: %s (status=%s)', e, getattr(e, 'status_code', None))\n    result = dict(inputs)","preventionTips":["Default fail_open=true already absorbs these errors; only set false when compliance requires it.","Size guardrail_timeout to your GraySwan latency (p99) to avoid timeout-induced failures.","Watch _log_guardrail_failure entries to distinguish auth vs capacity vs network faults."],"tags":["grayswan","guardrail","fail-closed","timeout","http-error"],"backgroundTag":"guardrail-api-request-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}