From 96af71264a277ea0c5aaf10e571317131804839b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 11 May 2026 22:43:28 +0000 Subject: [PATCH] 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 --- litellm/proxy/hooks/parallel_request_limiter.py | 17 ++++++++++------- .../proxy/hooks/parallel_request_limiter_v3.py | 8 +++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/litellm/proxy/hooks/parallel_request_limiter.py b/litellm/proxy/hooks/parallel_request_limiter.py index 43c5fc68723..03acd72b1c5 100644 --- a/litellm/proxy/hooks/parallel_request_limiter.py +++ b/litellm/proxy/hooks/parallel_request_limiter.py @@ -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())}, ) diff --git a/litellm/proxy/hooks/parallel_request_limiter_v3.py b/litellm/proxy/hooks/parallel_request_limiter_v3.py index cd797483b29..a3f677970a9 100644 --- a/litellm/proxy/hooks/parallel_request_limiter_v3.py +++ b/litellm/proxy/hooks/parallel_request_limiter_v3.py @@ -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),