refactor(proxy/hooks): raise ProxyRateLimitError from parallel-request limiters

Replaces HTTPException(status_code=429, ...) call sites in the v1 and v3
parallel-request limiters (key/team/user/model/customer rate limits) with
ProxyRateLimitError. Updates the raise_rate_limit_error helper's return type
annotation accordingly.

LIT-2968

Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com>
This commit is contained in:
Cursor Agent 2026-05-11 22:43:28 +00:00
parent 39a9968103
commit 96af71264a
No known key found for this signature in database
2 changed files with 13 additions and 12 deletions

View file

@ -3,7 +3,6 @@ import sys
from datetime import datetime, timedelta
from typing import TYPE_CHECKING, Any, List, Literal, Optional, Tuple, Union
from fastapi import HTTPException
from pydantic import BaseModel
from typing_extensions import TypedDict
@ -17,6 +16,7 @@ from litellm.proxy.auth.auth_utils import (
get_key_model_rpm_limit,
get_key_model_tpm_limit,
)
from litellm.proxy.common_utils.proxy_rate_limit_error import ProxyRateLimitError
if TYPE_CHECKING:
from opentelemetry.trace import Span as _Span
@ -95,8 +95,7 @@ class _PROXY_MaxParallelRequestsHandler(CustomLogger):
values_to_update_in_cache.append((request_count_api_key, new_val))
else:
raise HTTPException(
status_code=429,
raise ProxyRateLimitError(
detail=f"LiteLLM Rate Limit Handler for rate limit type = {rate_limit_type}. {CommonProxyErrors.max_parallel_request_limit_reached.value}. current rpm: {current['current_rpm']}, rpm limit: {rpm_limit}, current tpm: {current['current_tpm']}, tpm limit: {tpm_limit}, current max_parallel_requests: {current['current_requests']}, max_parallel_requests: {max_parallel_requests}",
headers={"retry-after": str(self.time_to_next_minute())},
)
@ -123,15 +122,19 @@ class _PROXY_MaxParallelRequestsHandler(CustomLogger):
def raise_rate_limit_error(
self, additional_details: Optional[str] = None
) -> HTTPException:
) -> ProxyRateLimitError:
"""
Raise an HTTPException with a 429 status code and a retry-after header
Raise a 429 with a retry-after header for litellm-proxy parallel-request limits.
Returns a :class:`ProxyRateLimitError`, which is both a
:class:`litellm.RateLimitError` (so callers can catch by category) and a
:class:`fastapi.HTTPException` (so the FastAPI dispatcher serializes it
correctly with status 429 and the supplied headers).
"""
error_message = "Max parallel request limit reached"
if additional_details is not None:
error_message = error_message + " " + additional_details
raise HTTPException(
status_code=429,
raise ProxyRateLimitError(
detail=f"Max parallel request limit reached {additional_details}",
headers={"retry-after": str(self.time_to_next_minute())},
)

View file

@ -23,8 +23,6 @@ from typing import (
cast,
)
from fastapi import HTTPException
from litellm import DualCache
from litellm._logging import verbose_proxy_logger
from litellm.constants import DYNAMIC_RATE_LIMIT_ERROR_THRESHOLD_PER_MINUTE
@ -34,6 +32,7 @@ from litellm.litellm_core_utils.prompt_templates.common_utils import (
)
from litellm.proxy._types import UserAPIKeyAuth
from litellm.proxy.auth.auth_utils import get_model_rate_limit_from_metadata
from litellm.proxy.common_utils.proxy_rate_limit_error import ProxyRateLimitError
from litellm.types.caching import RedisPipelineIncrementOperation
from litellm.types.llms.openai import BaseLiteLLMOpenAIResponseObject
from litellm.types.utils import ModelResponse, Usage
@ -1838,7 +1837,7 @@ class _PROXY_MaxParallelRequestsHandler_v3(CustomLogger):
response: RateLimitResponse,
descriptors: List[RateLimitDescriptor],
) -> None:
"""Handle rate limit exceeded error by raising HTTPException."""
"""Handle rate limit exceeded by raising :class:`ProxyRateLimitError` (a 429)."""
for status in response["statuses"]:
if status["code"] == "OVER_LIMIT":
descriptor_key = status["descriptor_key"]
@ -1869,8 +1868,7 @@ class _PROXY_MaxParallelRequestsHandler_v3(CustomLogger):
f"Limit resets at: {reset_time_formatted}"
)
raise HTTPException(
status_code=429,
raise ProxyRateLimitError(
detail=detail,
headers={
"retry-after": str(self.window_size),