litellm - ✅(Solved) Fix auth_exception_handler logs empty exception message and missing request context (model, key, IP) for ProxyException [1 pull requests, 1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
BerriAI/litellm#25361Fetched 2026-04-09 07:52:34
View on GitHub
Comments
1
Participants
1
Timeline
1
Reactions
0
Participants
Timeline (top)
commented ×1

When a request is rejected by _can_object_call_model (e.g., the requested model is not deployed or not allowed for the key), auth_exception_handler.py logs an exception with no message and omits critical debugging context. The LiteLLM UI shows nothing useful for these failures — the information is only partially available in raw pod logs.

Error Message

09:22:08 - LiteLLM Proxy:ERROR: auth_exception_handler.py:78 - litellm.proxy.proxy_server.user_api_key_auth(): Exception occured - Requester IP Address:35.191.114.47 Traceback (most recent call last): File ".../litellm/proxy/auth/user_api_key_auth.py", line 1044, in _user_api_key_auth_builder await can_key_call_model( ...<4 lines>... ) File ".../litellm/proxy/auth/auth_checks.py", line 2514, in can_key_call_model return _can_object_call_model( model=model, ...<4 lines>... object_type="key", ) File ".../litellm/proxy/auth/auth_checks.py", line 2465, in _can_object_call_model raise ProxyException( ...<6 lines>... ) litellm.proxy._types.ProxyException

Root Cause

When a request is rejected by _can_object_call_model (e.g., the requested model is not deployed or not allowed for the key), auth_exception_handler.py logs an exception with no message and omits critical debugging context. The LiteLLM UI shows nothing useful for these failures — the information is only partially available in raw pod logs.

PR fix notes

PR #25501: fix(proxy): log exception message and request context in auth_exception_handler

Description (problem / solution / changelog)

Relevant issues

Fixes #25361

Summary

  • ProxyException does not define __str__, so str(e) at auth_exception_handler.py:80 always produces an empty string. Replaced with getattr(e, "message", str(e)) which resolves the actual error text while remaining safe for standard exceptions.
  • Added route and model to the log message and structured extra dict so operators can correlate auth failures without digging through raw pod logs.
  • Applied the same getattr pattern to the two remaining str(e) sites in the HTTPException and generic-exception branches for consistency.

Test plan

  • Added test test_proxy_exception_message_logged_correctly in tests/test_litellm/proxy/auth/test_auth_exception_handler.py — asserts that ProxyException.message, route, and model all appear in the log output

Changed files

  • litellm/proxy/auth/auth_exception_handler.py (modified, +11/-5)
  • tests/test_litellm/proxy/auth/test_auth_exception_handler.py (modified, +55/-0)

Code Example

09:22:08 - LiteLLM Proxy:ERROR: auth_exception_handler.py:78 - litellm.proxy.proxy_server.user_api_key_auth(): Exception occured - 
Requester IP Address:35.191.114.47
Traceback (most recent call last):
  File ".../litellm/proxy/auth/user_api_key_auth.py", line 1044, in _user_api_key_auth_builder
    await can_key_call_model(
    ...<4 lines>...
    )
  File ".../litellm/proxy/auth/auth_checks.py", line 2514, in can_key_call_model
    return _can_object_call_model(
        model=model,
    ...<4 lines>...
        object_type="key",
    )
  File ".../litellm/proxy/auth/auth_checks.py", line 2465, in _can_object_call_model
    raise ProxyException(
    ...<6 lines>...
    )
litellm.proxy._types.ProxyException

---

logger.error(
    f"user_api_key_auth(): Exception occured - {str(e) or type(e).__name__}",
    extra={
        "requester_ip": request.client.host if request.client else "unknown",
        "model": getattr(request_data, "model", "unknown"),
        "key_alias": getattr(user_api_key_dict, "key_alias", "unknown"),
    }
)
RAW_BUFFERClick to expand / collapse

Summary

When a request is rejected by _can_object_call_model (e.g., the requested model is not deployed or not allowed for the key), auth_exception_handler.py logs an exception with no message and omits critical debugging context. The LiteLLM UI shows nothing useful for these failures — the information is only partially available in raw pod logs.

Expected Behavior

The LiteLLM UI (Logs/Requests view) and error logs should surface:

  • The exception message (what went wrong)
  • The model that was requested
  • The API key alias or hash (which key was used)
  • The requester IP address

Actual Behavior

In the UI

Failed auth requests (401s) do not appear in the LiteLLM UI Logs view at all. There is no way to inspect these failures from the UI — you have to go to raw pod logs.

In the pod logs

The log line at auth_exception_handler.py:78 reads:

09:22:08 - LiteLLM Proxy:ERROR: auth_exception_handler.py:78 - litellm.proxy.proxy_server.user_api_key_auth(): Exception occured - 
Requester IP Address:35.191.114.47
Traceback (most recent call last):
  File ".../litellm/proxy/auth/user_api_key_auth.py", line 1044, in _user_api_key_auth_builder
    await can_key_call_model(
    ...<4 lines>...
    )
  File ".../litellm/proxy/auth/auth_checks.py", line 2514, in can_key_call_model
    return _can_object_call_model(
        model=model,
    ...<4 lines>...
        object_type="key",
    )
  File ".../litellm/proxy/auth/auth_checks.py", line 2465, in _can_object_call_model
    raise ProxyException(
    ...<6 lines>...
    )
litellm.proxy._types.ProxyException

Problems:

  1. Exception message is empty — the string after Exception occured - is blank. ProxyException.__str__() or the exception's message field is not being included in the log.
  2. Traceback lines are compressed (...<N lines>...) hiding the model= argument, so you cannot see which model was requested.
  3. Requester IP is in the traceback body — it is logged, but buried inside the multi-line traceback rather than on the summary line, making it hard to grep or alert on.
  4. No key alias or hash — cannot tell which virtual key made the request.
  5. Nothing in the UI — the most critical gap. These 401 failures are completely invisible in the LiteLLM Logs UI. Operators have to SSH into pods and grep raw logs to discover these errors are happening at all.

Suggested Fix

UI

Show failed auth requests (401s) in the Logs/Requests view with reason, model, and key alias. Even a separate "Auth Failures" tab or filter would help.

Logging

In auth_exception_handler.py, log the exception message explicitly on the summary line:

logger.error(
    f"user_api_key_auth(): Exception occured - {str(e) or type(e).__name__}",
    extra={
        "requester_ip": request.client.host if request.client else "unknown",
        "model": getattr(request_data, "model", "unknown"),
        "key_alias": getattr(user_api_key_dict, "key_alias", "unknown"),
    }
)

And avoid compressing traceback frames for auth exceptions — the model= argument in the compressed lines is exactly the information needed to diagnose the error.

Impact

Without this, diagnosing auth failures in production requires:

  • Knowing to look in raw pod logs (not obvious from the UI)
  • Correlating multiple log lines across pods
  • No ability to identify the model or key from a single log entry

In our case, a burst of ~50 401 errors over 10 minutes (model not deployed on our proxy) was completely invisible in the UI and took significant effort to trace in pod logs.

Environment

  • LiteLLM version: production deployment
  • Python 3.13
  • Deployed on GKE

extent analysis

TL;DR

Modify the logging in auth_exception_handler.py to include the exception message, model, key alias, and requester IP address for better error diagnosis.

Guidance

  • Update the logging statement in auth_exception_handler.py to explicitly log the exception message, model, key alias, and requester IP address, as suggested in the issue.
  • Consider adding a separate "Auth Failures" tab or filter in the LiteLLM Logs UI to make failed auth requests more visible.
  • Avoid compressing traceback frames for auth exceptions to preserve critical diagnostic information.
  • Verify that the updated logging statement correctly includes the required information and that failed auth requests are visible in the LiteLLM Logs UI.

Example

The suggested logging statement update is provided in the issue:

logger.error(
    f"user_api_key_auth(): Exception occured - {str(e) or type(e).__name__}",
    extra={
        "requester_ip": request.client.host if request.client else "unknown",
        "model": getattr(request_data, "model", "unknown"),
        "key_alias": getattr(user_api_key_dict, "key_alias", "unknown"),
    }
)

This update includes the exception message, model, key alias, and requester IP address in the log entry.

Notes

The suggested fix focuses on improving logging and visibility of failed auth requests. However, it does not address the underlying issues causing the 401 errors. Additional investigation and fixes may be necessary to resolve the root causes of these errors.

Recommendation

Apply the suggested workaround by updating the logging statement in auth_exception_handler.py to improve error diagnosis and visibility of failed auth requests. This will provide more informative log entries and make it easier to identify and troubleshoot authentication issues.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING