{"record":{"id":"09d1bc1076efbe8a","repo":"BerriAI/litellm","slug":"failed-to-verify-request-safety-with-lasso-api-e","errorCode":null,"errorMessage":"Failed to verify request safety with Lasso API: {error}","messagePattern":"Failed to verify request safety with Lasso API: (.+?)","errorType":"exception","errorClass":"LassoGuardrailAPIError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/guardrails/guardrail_hooks/lasso/lasso.py","lineNumber":621,"sourceCode":"                \"message_type\": message_type,\n                \"error_type\": type(error).__name__,\n            },\n        )\n\n        # Handle specific error types if httpx is available\n        if HTTPX_AVAILABLE:\n            if isinstance(error, httpx.TimeoutException):\n                raise LassoGuardrailAPIError(\"Lasso API timeout\")\n            elif isinstance(error, httpx.HTTPStatusError):\n                if error.response.status_code == 401:\n                    raise LassoGuardrailMissingSecrets(\"Invalid API key\")\n                elif error.response.status_code == 429:\n                    raise LassoGuardrailAPIError(\"Lasso API rate limit exceeded\")\n                else:\n                    raise LassoGuardrailAPIError(f\"API error: {error.response.status_code}\")\n\n        # Generic error handling\n        raise LassoGuardrailAPIError(f\"Failed to verify request safety with Lasso API: {error}\")\n\n    def _log_masking_applied(\n        self,\n        message_type: Literal[\"PROMPT\", \"COMPLETION\"],\n        response: dict[str, Any],\n    ) -> None:\n        \"\"\"Log masking application with structured context.\"\"\"\n        conversation_id: Final = getattr(self, \"conversation_id\", \"unknown\")\n        verbose_proxy_logger.debug(\n            \"Lasso masking applied\",\n            extra={\n                \"guardrail_name\": getattr(self, \"guardrail_name\", \"unknown\"),\n                \"message_type\": message_type,\n                \"violations_count\": len(response.get(\"findings\", {})),\n                \"masked_fields\": len(response.get(\"messages\", [])),\n                \"conversation_id\": conversation_id,\n            },\n        )","sourceCodeStart":603,"sourceCodeEnd":639,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/guardrails/guardrail_hooks/lasso/lasso.py#L603-L639","documentation":"The generic fallback in _handle_api_error: it wraps every exception that is neither a httpx.TimeoutException nor a httpx.HTTPStatusError — connection refused, DNS resolution failures, TLS/SSL errors, JSON decoding problems — as well as ALL exceptions when httpx is not importable (HTTPX_AVAILABLE is False, so the specific isinstance branches are skipped). The original exception is appended after the colon and is the real diagnostic.","triggerScenarios":"httpx.ConnectError (connection refused), DNS failure resolving the Lasso host, SSL certificate verification failure behind a MITM/corporate proxy, or an environment where httpx is not installed so every error lands in this branch.","commonSituations":"Corporate HTTP(S)_PROXY env vars routing the guardrail's call through a dead or unreachable proxy; DNS misconfiguration in the container; a slim install missing the httpx dependency; self-signed TLS interceptors breaking the handshake to the Lasso endpoint.","solutions":["Read the inner exception text after the colon — it names the actual failure (connect error, DNS, SSL, ...).","Test basic connectivity from the same host/container: curl -v against the Lasso API base URL.","Install httpx (pip install 'litellm[proxy]' or pip install httpx) so HTTPX_AVAILABLE is true and specific error handling works.","Fix HTTP_PROXY/HTTPS_PROXY/NO_PROXY settings or the CA bundle (REQUESTS_CA_BUNDLE/SSL_CERT_FILE) if a corporate proxy or TLS interception is involved."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"# Preflight: catch DNS/proxy/egress issues before the first guarded request\nimport httpx, os, socket\n\ndef lasso_egress_ok() -> tuple[bool, str]:\n    base = os.environ.get(\"LASSO_API_BASE\", \"https://api.lasso.security\")\n    host = httpx.URL(base).host\n    try:\n        socket.getaddrinfo(host, 443)\n    except socket.gaierror:\n        return False, f\"DNS cannot resolve {host}\"\n    try:\n        httpx.head(base, timeout=5)\n    except httpx.HTTPError as e:\n        return False, f\"egress to {base} failed: {type(e).__name__}: {e}\"\n    return True, \"ok\"","typeGuard":"from litellm.proxy.guardrails.guardrail_hooks.lasso.lasso import LassoGuardrailAPIError\n\ndef is_lasso_connectivity_error(err: Exception) -> bool:\n    \"\"\"Generic-branch error (not timeout, not a mapped status) — usually connect/DNS/SSL.\"\"\"\n    msg = str(err)\n    return (\n        isinstance(err, LassoGuardrailAPIError)\n        and msg.startswith(\"Failed to verify request safety\")\n    )","tryCatchPattern":"from litellm.proxy.guardrails.guardrail_hooks.lasso.lasso import LassoGuardrailAPIError\n\ntry:\n    result = await guardrail_hook(data)\nexcept LassoGuardrailAPIError as e:\n    if str(e).startswith(\"Failed to verify request safety\"):\n        # log the inner cause verbatim — it names connect/DNS/SSL/httpx-missing\n        logger.error(\"lasso unreachable: %s\", e)\n        raise  # fix infra; retrying rarely helps until the cause is resolved\n    raise","preventionTips":["Bake httpx into the proxy image so HTTPX_AVAILABLE is always true and specific error mapping works.","Audit HTTP_PROXY/HTTPS_PROXY/NO_PROXY in the proxy environment — dead proxies are the top cause of this branch.","Run lasso_egress_ok() in the container as a readiness gate.","Install the corporate CA bundle (SSL_CERT_FILE/REQUESTS_CA_BUNDLE) when TLS interception is present."],"tags":["network","connection","lasso","guardrails","dependency"],"backgroundTag":"api-connection-error","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}