Skip to content

auth_exception_handler logs empty exception message and missing request context (model, key, IP) for ProxyException #25361

@madhu19991

Description

@madhu19991

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions