BerriAI/litellm · error · UnauthorizedError
{e}
Error message
{e} What it means
Raised by ModelsManagementClient.list() when GET {base_url}/models returns HTTP 401, converted to UnauthorizedError (redacted message; original on .orig_exception; other non-2xx re-raise as plain requests HTTPError). /models is the OpenAI-style model list that many proxies leave public, so this 401 specifically means your proxy enforces auth on it (master key / strict auth configured) and the client's Bearer credentials were absent or rejected.
Source
Thrown at litellm/proxy/client/models.py:63
Raises:
UnauthorizedError: If the request fails with a 401 status code
requests.exceptions.RequestException: If the request fails with any other error
"""
url: Final = f"{self._base_url}/models"
request: Final = requests.Request("GET", url, headers=self._get_headers())
if return_request:
return request
# Prepare and send the request
session: Final = requests.Session()
try:
response: Final = session.send(request.prepare())
response.raise_for_status()
return response.json()["data"]
except requests.exceptions.HTTPError as e:
if e.response.status_code == 401:
raise UnauthorizedError(e)
raise
def new(
self,
model_name: str,
model_params: dict[str, Any],
model_info: dict[str, Any] | None = None,
return_request: bool = False,
) -> dict[str, Any] | requests.Request:
"""
Add a new model to the proxy.
Args:
model_name (str): Name of the model to add
model_params (Dict[str, Any]): Parameters for the model (e.g., model type, api_base, api_key)
model_info (Optional[Dict[str, Any]]): Additional information about the model
return_request (bool): If True, returns the prepared request object instead of executing it
View on GitHub (pinned to 77b7c6c40c)
Solutions
- Pass a valid key: ModelsManagementClient(base_url, api_key=os.environ["LITELLM_MASTER_KEY"]).list()
- Confirm enforcement expectations: curl $BASE_URL/models (no auth) vs curl -H "Authorization: Bearer $KEY" $BASE_URL/models
- Rotate/refresh the key if the proxy rejects it
- Check base_url — a wrong port can hit a different service that answers 401
Example fix
# before
from litellm.proxy.client.models import ModelsManagementClient
models = ModelsManagementClient("http://localhost:4000")
models.list() # UnauthorizedError
# after
import os
models = ModelsManagementClient("http://localhost:4000", api_key=os.environ["LITELLM_MASTER_KEY"])
models.list() Defensive patterns
Strategy: try-catch
Validate before calling
import requests
def models_listable(base_url: str, api_key: str | None) -> bool:
r = requests.get(
f"{base_url.rstrip('/')}/models",
headers={"Authorization": f"Bearer {api_key}"} if api_key else {},
timeout=10,
)
return r.status_code != 401 Try / catch
from litellm.proxy.client.exceptions import UnauthorizedError
import requests
try:
models = client.list()
except UnauthorizedError:
raise RuntimeError("proxy requires auth for /models — supply a valid key") from None
except requests.exceptions.HTTPError as e:
handle(e.response) # 5xx etc. Prevention
- Don't assume /models is public — pass the key even for model listing in prod
- Smoke-test GET {base_url}/models with the intended credentials during deployment checks
- Keep dev (open) and prod (authed) proxy configurations in sync to avoid surprise 401s
When it happens
Trigger: Calling models.list() with api_key=None against a proxy configured with a master_key or otherwise requiring auth; a wrong/rotated key; a virtual key the proxy refuses for this route.
Common situations: Code written against an open dev proxy moved to a hardened prod proxy; env var with the key not set in the new deployment; key rotated during incident response.
Related errors
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/d6cd1f2306e981c0.
Report an issue: GitHub.