From f5a4bc14a065625685add255b4365af24087520c Mon Sep 17 00:00:00 2001 From: Yucheng Zhu Date: Fri, 28 Aug 2026 00:19:17 -0700 Subject: [PATCH] fix(auth): retain invalid virtual key warning logs Co-Authored-By: Claude --- litellm/proxy/auth/auth_exception_handler.py | 34 +++++++++++-------- .../proxy/auth/test_auth_exception_handler.py | 20 +++++++++-- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/litellm/proxy/auth/auth_exception_handler.py b/litellm/proxy/auth/auth_exception_handler.py index d7964f9ceaa..c2aebfd270d 100644 --- a/litellm/proxy/auth/auth_exception_handler.py +++ b/litellm/proxy/auth/auth_exception_handler.py @@ -115,21 +115,27 @@ class UserAPIKeyAuthExceptionHandler: and e.status_code == status.HTTP_401_UNAUTHORIZED and "LiteLLM Virtual Key expected" in str(e.detail) ) - log_fn: Final = ( - verbose_proxy_logger.info - if is_invalid_virtual_key and not litellm.log_client_error_tracebacks - else ( - verbose_proxy_logger.error - if is_expected_client_error(e) and not litellm.log_client_error_tracebacks - else verbose_proxy_logger.exception + if is_invalid_virtual_key and not litellm.log_client_error_tracebacks: + verbose_proxy_logger.warning( + "litellm.proxy.proxy_server.user_api_key_auth(): Exception occured - %s\nRequester IP Address:%s", + e, + requester_ip, + extra={"requester_ip": requester_ip}, + ) + elif is_expected_client_error(e) and not litellm.log_client_error_tracebacks: + verbose_proxy_logger.error( + "litellm.proxy.proxy_server.user_api_key_auth(): Exception occured - %s\nRequester IP Address:%s", + e, + requester_ip, + extra={"requester_ip": requester_ip}, + ) + else: + verbose_proxy_logger.exception( + "litellm.proxy.proxy_server.user_api_key_auth(): Exception occured - %s\nRequester IP Address:%s", + e, + requester_ip, + extra={"requester_ip": requester_ip}, ) - ) - log_fn( - "litellm.proxy.proxy_server.user_api_key_auth(): Exception occured - %s\nRequester IP Address:%s", - e, - requester_ip, - extra={"requester_ip": requester_ip}, - ) # Log this exception to OTEL, Datadog etc. Reuse the identity resolved # before the failure (team alias/id, metadata, user) so the failed span diff --git a/tests/test_litellm/proxy/auth/test_auth_exception_handler.py b/tests/test_litellm/proxy/auth/test_auth_exception_handler.py index 0d3ef0b54a9..dbc587a6d3f 100644 --- a/tests/test_litellm/proxy/auth/test_auth_exception_handler.py +++ b/tests/test_litellm/proxy/auth/test_auth_exception_handler.py @@ -713,10 +713,10 @@ async def test_auth_failure_ip_stamp_does_not_mutate_callers_request_data(): status_code=status.HTTP_401_UNAUTHORIZED, detail="LiteLLM Virtual Key expected. Received=unde****ined, expected to start with 'sk-'.", ), - logging.INFO, + logging.WARNING, False, False, - id="invalid_virtual_key_logs_at_info_without_traceback", + id="invalid_virtual_key_logs_at_warning_without_traceback", ), pytest.param( HTTPException( @@ -728,6 +728,16 @@ async def test_auth_failure_ip_stamp_does_not_mutate_callers_request_data(): True, id="invalid_virtual_key_keeps_traceback_opt_in", ), + pytest.param( + HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Authentication Error", + ), + logging.ERROR, + False, + False, + id="other_http_401_keeps_error_level_without_traceback", + ), pytest.param( ProxyException( message="Authentication Error", type=ProxyErrorTypes.auth_error, param=None, code=401 @@ -757,7 +767,11 @@ async def test_auth_failure_ip_stamp_does_not_mutate_callers_request_data(): ], ) async def test_handle_authentication_error_traceback_only_for_unexpected_errors( - auth_error, expected_level, expect_traceback, log_client_error_tracebacks, caplog + auth_error: Exception, + expected_level: int, + expect_traceback: bool, + log_client_error_tracebacks: bool, + caplog: pytest.LogCaptureFixture, ): """Regression for LIT-6043: expected 4xx auth rejections must not format a traceback via logger.exception; unexpected errors must keep it."""