mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-12 23:01:41 +00:00
fix(proxy): populate Exception.args so str(ProxyException) returns message (LIT-3094) (#29015)
* fix(proxy): populate Exception.args so str(ProxyException) returns message
Adds super().__init__(self.message) to ProxyException.__init__ so that
str(exc) returns the stored message instead of empty string. Fixes LIT-3094.
* test(proxy): regression tests for ProxyException.args (LIT-3094)
* fix(proxy): populate Exception.args so str(ProxyException) returns message (LIT-3094)
* fix(proxy): clean up unintended drift; keep only ProxyException.args fix (LIT-3094)
(cherry picked from commit 1fe911d89d)
This commit is contained in:
parent
d0f29513b7
commit
2f33a86e2f
2 changed files with 78 additions and 0 deletions
|
|
@ -3695,6 +3695,11 @@ class ProxyException(Exception):
|
|||
provider_specific_fields: Optional[dict] = None,
|
||||
):
|
||||
self.message = str(message)
|
||||
# Populate Exception.args so str(self) returns the message.
|
||||
# Without this, logging paths that call str(original_exception)
|
||||
# (e.g. StandardLoggingPayloadSetup.get_error_information) record an
|
||||
# empty error_message for ProxyException-based failures. See LIT-3094.
|
||||
super().__init__(self.message)
|
||||
self.type = type
|
||||
self.param = param
|
||||
self.openai_code = openai_code or code
|
||||
|
|
|
|||
|
|
@ -87,3 +87,76 @@ def test_user_api_key_auth_hashes_authorization_header_form_of_key():
|
|||
assert from_header.api_key == baseline.api_key
|
||||
assert from_header.token == baseline.token
|
||||
assert not from_header.api_key.lower().startswith("bearer")
|
||||
|
||||
|
||||
# === Regression tests for LIT-3094: ProxyException must populate Exception.args
|
||||
# so logging integrations using str(exc) record a non-empty error_message. ===
|
||||
|
||||
|
||||
def test_proxy_exception_str_returns_message():
|
||||
"""str(ProxyException) must return the stored message, not '' (LIT-3094)."""
|
||||
from litellm.proxy._types import ProxyException
|
||||
|
||||
msg = "key not allowed to access model"
|
||||
exc = ProxyException(message=msg, type="auth_error", param=None, code=401)
|
||||
assert str(exc) == msg
|
||||
assert exc.args == (msg,)
|
||||
assert exc.message == msg
|
||||
|
||||
|
||||
def test_proxy_exception_populates_standard_logging_error_message():
|
||||
"""The full logging path used by proxy callbacks must capture the message
|
||||
instead of recording an empty error_message (LIT-3094 report)."""
|
||||
from litellm.litellm_core_utils.litellm_logging import (
|
||||
StandardLoggingPayloadSetup,
|
||||
)
|
||||
from litellm.proxy._types import ProxyException
|
||||
|
||||
msg = "Authentication Error, Invalid proxy server token passed."
|
||||
exc = ProxyException(message=msg, type="auth_error", param=None, code=401)
|
||||
info = StandardLoggingPayloadSetup.get_error_information(original_exception=exc)
|
||||
assert info["error_message"] == msg
|
||||
assert info["error_class"] == "ProxyException"
|
||||
assert info["error_code"] == "401"
|
||||
|
||||
|
||||
def test_proxy_exception_to_dict_unchanged():
|
||||
"""to_dict() shape must remain backwards-compatible after the fix."""
|
||||
from litellm.proxy._types import ProxyException
|
||||
|
||||
exc = ProxyException(
|
||||
message="boom", type="invalid_request_error", param="model", code=400
|
||||
)
|
||||
d = exc.to_dict()
|
||||
assert d == {
|
||||
"message": "boom",
|
||||
"type": "invalid_request_error",
|
||||
"param": "model",
|
||||
"code": "400",
|
||||
}
|
||||
|
||||
|
||||
def test_proxy_exception_routing_code_override_still_works():
|
||||
"""The 'No healthy deployment available' -> 429 remapping must survive
|
||||
the super().__init__() addition."""
|
||||
from litellm.proxy._types import ProxyException
|
||||
|
||||
exc = ProxyException(
|
||||
message="No healthy deployment available for model=foo",
|
||||
type="router_error",
|
||||
param=None,
|
||||
code=500,
|
||||
)
|
||||
assert exc.code == "429"
|
||||
assert str(exc) == "No healthy deployment available for model=foo"
|
||||
|
||||
|
||||
def test_proxy_exception_non_string_message_coerced():
|
||||
"""Non-string `message` must still be coerced to str via self.message =
|
||||
str(message), and Exception.args must reflect the coerced value."""
|
||||
from litellm.proxy._types import ProxyException
|
||||
|
||||
exc = ProxyException(message=42, type="x", param=None, code=400)
|
||||
assert exc.message == "42"
|
||||
assert str(exc) == "42"
|
||||
assert exc.args == ("42",)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue