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
- Pass an admin-capable key: KeysManagementClient(base_url, api_key=os.environ["LITELLM_MASTER_KEY"]).list()
- Confirm with curl: curl -H "Authorization: Bearer $KEY" "$BASE_URL/key/list?page=1&size=10"
- If only a 403 appears after fixing auth, grant the key list-permissions or use the master key
- 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
- Use the master/admin key for /key/list; virtual keys need explicit list permissions
- Check the resolved api_key is non-empty before building management clients
- Distinguish 403 (authenticated but unprivileged) from 401 in your handler — only the former maps to UnauthorizedError
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
- {e}
- {e}
- {e}
- Authentication failed. Check your Arize Phoenix API key and
- Authentication failed. Check your BitBucket access token and
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/382c5e6d8fa4a39e.
Report an issue: GitHub.