diff --git a/litellm/litellm_core_utils/exception_mapping_utils.py b/litellm/litellm_core_utils/exception_mapping_utils.py index 1a43ff2e17..f8c786daef 100644 --- a/litellm/litellm_core_utils/exception_mapping_utils.py +++ b/litellm/litellm_core_utils/exception_mapping_utils.py @@ -3,6 +3,7 @@ import traceback from typing import Any, Optional import httpx +import re import litellm from litellm._logging import verbose_logger @@ -45,13 +46,20 @@ class ExceptionCheckers: if not isinstance(error_str, str): return False - if "429" in error_str or "rate limit" in error_str.lower(): + # Only treat 429 as a rate limit signal when it appears as a standalone token + if re.search(r"\b429\b", error_str): + return True + + _error_str_lower = error_str.lower() + + # Match "rate limit" (including variations like rate-limit / rate_limit) + if re.search(r"rate[\s_\-]*limit", _error_str_lower): return True ####################################### # Mistral API returns this error string ######################################### - if "service tier capacity exceeded" in error_str.lower(): + if "service tier capacity exceeded" in _error_str_lower: return True return False @@ -155,9 +163,6 @@ def _get_response_headers(original_exception: Exception) -> Optional[httpx.Heade return _response_headers -import re - - def extract_and_raise_litellm_exception( response: Optional[Any], error_str: str, diff --git a/tests/test_litellm/litellm_core_utils/test_exception_mapping_utils.py b/tests/test_litellm/litellm_core_utils/test_exception_mapping_utils.py index 2487479a8c..d7da759287 100644 --- a/tests/test_litellm/litellm_core_utils/test_exception_mapping_utils.py +++ b/tests/test_litellm/litellm_core_utils/test_exception_mapping_utils.py @@ -57,6 +57,20 @@ def test_is_error_str_context_window_exceeded(error_str, expected): class TestExceptionCheckers: """Test the ExceptionCheckers utility methods""" + def test_is_error_str_rate_limit_ignores_embedded_numbers(self): + """An arbitrary 429 inside user-provided payload must not trigger rate-limit detection""" + + error_str = "Invalid user message={'role': 'user', 'content': [{'text': 'payload429snippet'}]}" + result = ExceptionCheckers.is_error_str_rate_limit(error_str) + assert result is False + + def test_is_error_str_rate_limit_detects_true_rate_limit(self): + """A real rate-limit error string should still be detected""" + + error_str = "RateLimitError: OpenAIException - You exceeded your current quota. (status code 429)" + result = ExceptionCheckers.is_error_str_rate_limit(error_str) + assert result is True + def test_is_azure_content_policy_violation_error_with_policy_violation_text(self): """Test detection of Azure content policy violation with explicit policy violation text"""