mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
fix(exception_mapping): handle exceptions without response parameter (#18919)
When extract_and_raise_litellm_exception tries to raise a LiteLLM exception from an error string, it was always passing the response parameter. However, some exceptions like APIConnectionError don't accept this parameter, causing a TypeError. This fix tries to raise the exception with the response parameter first, and falls back to raising without it if a TypeError occurs. This fixes the error: TypeError: APIConnectionError.__init__() got an unexpected keyword argument 'response' Which was occurring when Gemini returned UNEXPECTED_TOOL_CALL finish reason and LiteLLM tried to convert the error to an APIConnectionError. Fixes: cascading error when Gemini uses thinking feature (__thought__ tool calls)
This commit is contained in:
parent
f76938af5e
commit
d94af171db
2 changed files with 93 additions and 6 deletions
|
|
@ -197,12 +197,22 @@ def extract_and_raise_litellm_exception(
|
|||
exception_name = exception_name.strip().replace("litellm.", "")
|
||||
raised_exception_obj = getattr(litellm, exception_name, None)
|
||||
if raised_exception_obj:
|
||||
raise raised_exception_obj(
|
||||
message=error_str,
|
||||
llm_provider=custom_llm_provider,
|
||||
model=model,
|
||||
response=response,
|
||||
)
|
||||
# Try with response parameter first, fall back to without it
|
||||
# Some exceptions (e.g., APIConnectionError) don't accept response param
|
||||
try:
|
||||
raise raised_exception_obj(
|
||||
message=error_str,
|
||||
llm_provider=custom_llm_provider,
|
||||
model=model,
|
||||
response=response,
|
||||
)
|
||||
except TypeError:
|
||||
# Exception doesn't accept response parameter
|
||||
raise raised_exception_obj(
|
||||
message=error_str,
|
||||
llm_provider=custom_llm_provider,
|
||||
model=model,
|
||||
)
|
||||
|
||||
|
||||
def exception_type( # type: ignore # noqa: PLR0915
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ sys.path.insert(
|
|||
from litellm.litellm_core_utils.exception_mapping_utils import (
|
||||
ExceptionCheckers,
|
||||
exception_type,
|
||||
extract_and_raise_litellm_exception,
|
||||
)
|
||||
|
||||
# Test cases for is_error_str_context_window_exceeded
|
||||
|
|
@ -269,3 +270,79 @@ def test_vertex_ai_rate_limit_error_mapping(error_message, should_raise_rate_lim
|
|||
original_exception=original_exception,
|
||||
custom_llm_provider=custom_llm_provider,
|
||||
)
|
||||
|
||||
|
||||
class TestExtractAndRaiseLitellmException:
|
||||
"""Tests for extract_and_raise_litellm_exception function"""
|
||||
|
||||
def test_extract_and_raise_api_connection_error_without_response(self):
|
||||
"""
|
||||
Test that APIConnectionError can be raised without response parameter.
|
||||
|
||||
This is a regression test for the bug where extract_and_raise_litellm_exception
|
||||
would fail with TypeError when trying to raise APIConnectionError with a
|
||||
response parameter, since APIConnectionError doesn't accept that parameter.
|
||||
|
||||
Relevant Issue: https://github.com/BerriAI/litellm/issues/XXXXX
|
||||
"""
|
||||
error_str = "litellm.APIConnectionError: GeminiException - some error message"
|
||||
|
||||
with pytest.raises(litellm.APIConnectionError) as excinfo:
|
||||
extract_and_raise_litellm_exception(
|
||||
response=None,
|
||||
error_str=error_str,
|
||||
model="gemini/gemini-3-pro-preview",
|
||||
custom_llm_provider="gemini",
|
||||
)
|
||||
|
||||
assert "APIConnectionError" in str(excinfo.value)
|
||||
|
||||
def test_extract_and_raise_bad_request_error_with_response(self):
|
||||
"""
|
||||
Test that BadRequestError can be raised with response parameter.
|
||||
|
||||
BadRequestError does accept the response parameter, so this should work.
|
||||
"""
|
||||
error_str = "litellm.BadRequestError: Invalid request format"
|
||||
|
||||
with pytest.raises(litellm.BadRequestError) as excinfo:
|
||||
extract_and_raise_litellm_exception(
|
||||
response=None,
|
||||
error_str=error_str,
|
||||
model="gpt-4",
|
||||
custom_llm_provider="openai",
|
||||
)
|
||||
|
||||
assert "BadRequestError" in str(excinfo.value)
|
||||
|
||||
def test_extract_and_raise_context_window_exceeded_error(self):
|
||||
"""
|
||||
Test that ContextWindowExceededError can be raised.
|
||||
"""
|
||||
error_str = "litellm.ContextWindowExceededError: Token limit exceeded"
|
||||
|
||||
with pytest.raises(litellm.ContextWindowExceededError) as excinfo:
|
||||
extract_and_raise_litellm_exception(
|
||||
response=None,
|
||||
error_str=error_str,
|
||||
model="gpt-4",
|
||||
custom_llm_provider="openai",
|
||||
)
|
||||
|
||||
assert "ContextWindowExceededError" in str(excinfo.value)
|
||||
|
||||
def test_no_exception_raised_for_non_litellm_error(self):
|
||||
"""
|
||||
Test that no exception is raised for non-litellm error strings.
|
||||
"""
|
||||
error_str = "Some generic error that is not a litellm exception"
|
||||
|
||||
# Should not raise any exception
|
||||
result = extract_and_raise_litellm_exception(
|
||||
response=None,
|
||||
error_str=error_str,
|
||||
model="gpt-4",
|
||||
custom_llm_provider="openai",
|
||||
)
|
||||
|
||||
assert result is None
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue