{"record":{"id":"0cdebef7a8c6dfa2","repo":"BerriAI/litellm","slug":"lasso-api-rate-limit-exceeded","errorCode":null,"errorMessage":"Lasso API rate limit exceeded","messagePattern":"Lasso API rate limit exceeded","errorType":"exception","errorClass":"LassoGuardrailAPIError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/guardrails/guardrail_hooks/lasso/lasso.py","lineNumber":616,"sourceCode":"        verbose_proxy_logger.error(\n            \"Error calling Lasso API: %s\",\n            error,\n            extra={\n                \"guardrail_name\": getattr(self, \"guardrail_name\", \"unknown\"),\n                \"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,","sourceCodeStart":598,"sourceCodeEnd":634,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/guardrails/guardrail_hooks/lasso/lasso.py#L598-L634","documentation":"Raised as LassoGuardrailAPIError when the Lasso API responds with HTTP 429: your organization has exceeded its Lasso rate limit. The guardrail cannot evaluate the request, so litellm fails the call instead of skipping moderation.","triggerScenarios":"A guardrail hook sends a request to the Lasso API and the response status is 429 (httpx raises HTTPStatusError with response.status_code == 429), which _handle_api_error re-raises as 'Lasso API rate limit exceeded'.","commonSituations":"High RPS through the proxy with every call guarded; burst traffic (batch jobs, load tests); a Lasso plan with lower limits than production traffic; multiple litellm instances or environments sharing one Lasso key.","solutions":["Retry with exponential backoff and jitter, honoring the Retry-After header if Lasso sends one.","Reduce guardrail evaluation pressure: narrow the guardrail to the hooks/modes you actually need (e.g. only pre_call) and avoid guarding low-risk traffic.","Check your Lasso plan's rate limits and request a limit increase if sustained traffic legitimately exceeds them.","Distribute traffic across multiple Lasso keys/workspaces if your plan supports it."],"exampleFix":"# before\nresp = await client.post(lasso_url, headers=headers, json=payload)\n\n# after — honor 429 with backoff (tenacity)\nfrom tenacity import retry, stop_after_attempt, wait_exponential_jitter\n\n@retry(stop=stop_after_attempt(5), wait=wait_exponential_jitter(1, 30),\n       retry=retry_if_exception=lambda e: getattr(e, \"response\", None) is not None and e.response.status_code == 429)\nasync def call_lasso():\n    return await client.post(lasso_url, headers=headers, json=payload)","handlingStrategy":"retry","validationCode":null,"typeGuard":"from litellm.proxy.guardrails.guardrail_hooks.lasso.lasso import LassoGuardrailAPIError\n\ndef is_lasso_rate_limit(err: Exception) -> bool:\n    \"\"\"True when the wrapped error is a 429 from Lasso — safe to back off and retry.\"\"\"\n    return isinstance(err, LassoGuardrailAPIError) and \"rate limit\" in str(err).lower()","tryCatchPattern":"import asyncio\nfrom litellm.proxy.guardrails.guardrail_hooks.lasso.lasso import LassoGuardrailAPIError\n\nasync def call_with_backoff(hook, data, attempts: int = 5):\n    for i in range(attempts):\n        try:\n            return await hook(data)\n        except LassoGuardrailAPIError as e:\n            if \"rate limit\" not in str(e).lower() or i == attempts - 1:\n                raise\n            await asyncio.sleep(min(2 ** i + 1, 30))  # exponential backoff + jitter","preventionTips":["Know your Lasso plan's RPS limit and size the proxy/guardrail traffic under it.","Enable guardrails only on the hooks you need (e.g. pre_call only) to cut call volume.","Cache moderation verdicts for identical short inputs where policy allows.","Alert on 429 frequency so you upgrade limits before users see failures."],"tags":["rate-limit","lasso","guardrails","http-429"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}