BerriAI/litellm · error · ProxyException

f"Authentication Error({e})"

Error message

f"Authentication Error({e})"

What it means

/user/update wraps every failure into a ProxyException with type auth_error. For HTTPExceptions it copies e.detail as the message; the literal 'Authentication Error({e})' text only appears through the getattr(e, 'detail', ...) fallback when the exception carries no detail attribute - rare, e.g. a malformed or bare HTTPException raised deep inside helpers. The response code is the original status_code when present, else 400.

Source

Thrown at litellm/proxy/management_endpoints/internal_user_endpoints.py:1590

        - key_alias: Optional[str] - [NOT IMPLEMENTED].
        - object_permission: Optional[LiteLLM_ObjectPermissionBase] - internal user-specific object permission. Example - {"vector_stores": ["vector_store_1"], "mcp_servers": ["github"], "mcp_tool_permissions": {"github": ["list_issues"]}}. The MCP grants act as a ceiling on every key this user holds. IF null or {} then no object permission.
        - prompts: Optional[List[str]] - List of allowed prompts for the user. If specified, the user will only be able to use these specific prompts.
        - budget_limits: Optional[list] - List of concurrent budget windows for the user. Each window specifies a budget_limit, time_period, and optional budget_duration. Example - [{"budget_limit": 10.0, "time_period": "1d"}, {"budget_limit": 50.0, "time_period": "7d"}].

    """
    try:
        verbose_proxy_logger.debug("/user/update: Received data = %s", data)

        response: Final = await _update_single_user_helper(
            user_request=data,
            user_api_key_dict=user_api_key_dict,
        )
        return response
    except Exception as e:
        verbose_proxy_logger.exception("litellm.proxy.proxy_server.user_update(): Exception occured - %s", e)
        verbose_proxy_logger.debug(traceback.format_exc())
        if isinstance(e, HTTPException):
            raise ProxyException(
                message=getattr(e, "detail", f"Authentication Error({e})"),
                type=ProxyErrorTypes.auth_error,
                param=getattr(e, "param", "None"),
                code=getattr(e, "status_code", status.HTTP_400_BAD_REQUEST),
            )
        elif isinstance(e, ProxyException):
            raise e
        raise ProxyException(
            message="Authentication Error, " + str(e),
            type=ProxyErrorTypes.auth_error,
            param=getattr(e, "param", "None"),
            code=status.HTTP_400_BAD_REQUEST,
        )


async def bulk_update_processed_users(
    users_to_update: list[UpdateUserRequest],
    user_api_key_dict: UserAPIKeyAuth,

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Read the server logs first - the handler logs 'user_update(): Exception occured' plus the full traceback before wrapping
  2. Fix the underlying exception; in practice it is almost always one of the specific 4xx errors from this file (missing id, permissions, DB)
  3. Upgrade LiteLLM if the traceback shows a library-internal raise site
Defensive patterns

Strategy: try-catch

Try / catch

except requests.HTTPError as e:
    body = e.response.json() if e.response is not None else {}
    err = body.get("error", {}) if isinstance(body.get("error"), dict) else {}
    if err.get("type") == "auth_error" and str(err.get("message", "")).startswith("Authentication Error"):
        # generic wrapper: the real cause is in server logs; do not treat as an auth problem
        ...

Prevention

When it happens

Trigger: Any exception without a .detail attribute escaping the update pipeline during POST /user/update - a bare HTTPException(), a library-internal raise site, or custom exception types raised by hooks/helpers.

Common situations: Version drift where a helper raises a non-standard exception; seeing a generic auth message that actually masks a validation or database problem; debugging from the wrapped message instead of server logs.

Understand the failure class

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/4c9de4f82ecc17f8. Report an issue: GitHub.