BerriAI/litellm · error · UnauthorizedError

{e}

Error message

{e}

What it means

Raised by KeysManagementClient.list() when GET {base_url}/key/list (with whatever of page/size/user_id/team_id/organization_id/key_hash/key_alias/return_full_object/include_team_keys you passed) returns HTTP 401. The client converts 401 to UnauthorizedError (message is the redacted requests HTTPError text, original kept on .orig_exception); every other non-2xx — including 403 insufficient-role — re-raises as a plain requests HTTPError. Key listing is an admin-tier operation, so end-user keys are rejected.

Source

Thrown at litellm/proxy/client/keys.py:107

            params["key_alias"] = key_alias
        if return_full_object is not None:
            params["return_full_object"] = str(return_full_object).lower()
        if include_team_keys is not None:
            params["include_team_keys"] = str(include_team_keys).lower()

        request: Final = requests.Request("GET", url, headers=self._get_headers(), params=params)

        if return_request:
            return request

        session: Final = requests.Session()
        try:
            response: Final = session.send(request.prepare())
            response.raise_for_status()
            return response.json()
        except requests.exceptions.HTTPError as e:
            if e.response.status_code == 401:
                raise UnauthorizedError(e)
            raise

    def generate(
        self,
        models: builtins.list[str] | None = None,
        aliases: dict[str, str] | None = None,
        spend: float | None = None,
        duration: str | None = None,
        key_alias: str | None = None,
        team_id: str | None = None,
        user_id: str | None = None,
        budget_id: str | None = None,
        config: dict[str, Any] | None = None,
        return_request: bool = False,
    ) -> dict[str, Any] | requests.Request:
        """
        Generate an API key based on the provided data.

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Pass an admin-capable key: KeysManagementClient(base_url, api_key=os.environ["LITELLM_MASTER_KEY"]).list()
  2. Confirm with curl: curl -H "Authorization: Bearer $KEY" "$BASE_URL/key/list?page=1&size=10"
  3. If only a 403 appears after fixing auth, grant the key list-permissions or use the master key
  4. Reissue/rotate the key if the proxy no longer recognizes it

Example fix

# before
from litellm.proxy.client.keys import KeysManagementClient
keys = KeysManagementClient("http://localhost:4000")
keys.list()  # UnauthorizedError

# after
import os
keys = KeysManagementClient("http://localhost:4000", api_key=os.environ["LITELLM_MASTER_KEY"])
keys.list()
Defensive patterns

Strategy: try-catch

Validate before calling

import requests

def can_list_keys(base_url: str, api_key: str | None) -> bool:
    if not api_key:
        return False
    r = requests.get(
        f"{base_url.rstrip('/')}/key/list",
        headers={"Authorization": f"Bearer {api_key}"},
        params={"page": 1, "size": 1},
        timeout=10,
    )
    return r.status_code != 401

Try / catch

from litellm.proxy.client.exceptions import UnauthorizedError
import requests

try:
    page = keys.list(page=1, size=50)
except UnauthorizedError:
    rotate_credentials()  # 401: wrong/absent/revoked key — no point retrying
except requests.exceptions.HTTPError as e:
    if e.response is not None and e.response.status_code == 403:
        grant_list_permission_or_use_master_key()
    raise

Prevention

When it happens

Trigger: Listing keys with no api_key configured (no Authorization header sent) against an auth-enforcing proxy; using a virtual key that lacks permission to list keys; a key that was deleted or expired server-side.

Common situations: Reporting scripts authenticating with a team member's key instead of the master key; proxy hardened with a master_key after the script was written; rotated keys not propagated to configuration.

Related errors


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