BerriAI/litellm · error · HTTPException
f"User not found: {user_id}"
Error message
f"User not found: {user_id}" What it means
GET /v2/user/info runs _check_user_info_v2_access (allows self-lookup, proxy-admin roles, and team-admin over the target) which loads the target user row and returns it when allowed, None otherwise. A None result - either the user does not exist OR the caller is not permitted - produces 404 'User not found: {user_id}'. Returning 404 for both cases avoids leaking which user ids exist.
Source
Thrown at litellm/proxy/management_endpoints/internal_user_endpoints.py:1042
if user_id is None:
user_id = user_api_key_dict.user_id
if user_id is None:
raise HTTPException(
status_code=400,
detail="user_id is required. Either pass it as a query parameter or authenticate with a user-bound key.",
)
# Check access — returns the user row if allowed, None otherwise.
# This avoids a redundant DB fetch since the access check already
# loads the target user for team-admin verification.
user_row: Final = await _check_user_info_v2_access(
user_api_key_dict=user_api_key_dict,
target_user_id=user_id,
)
if user_row is None:
raise HTTPException(
status_code=404,
detail=f"User not found: {user_id}",
)
user_data: Final = user_row.model_dump()
return UserInfoV2Response(
user_id=user_data.get("user_id", user_id),
user_email=user_data.get("user_email"),
user_alias=user_data.get("user_alias"),
user_role=user_data.get("user_role"),
spend=user_data.get("spend", 0.0),
max_budget=user_data.get("max_budget"),
models=user_data.get("models") or [],
budget_duration=user_data.get("budget_duration"),
budget_reset_at=user_data.get("budget_reset_at"),
metadata=_redact_scim_enterprise_metadata(user_data.get("metadata")),
created_at=user_data.get("created_at"),View on GitHub (pinned to 77b7c6c40c)
Solutions
- Verify the id exists via GET /user/list (with an admin key) and fix typos
- Use a proxy-admin key, or the target user's own key for self-lookup
- If team-based access is expected, confirm the caller is actually an admin of a team that contains the target user
Example fix
# before: internal-user key asking for another user -> 404 GET /v2/user/info?user_id=other-user -H 'Authorization: Bearer sk-internal' # after: self lookup, or admin key GET /v2/user/info -H 'Authorization: Bearer sk-internal' GET /v2/user/info?user_id=other-user -H 'Authorization: Bearer sk-admin' # 200
Defensive patterns
Strategy: validation
Validate before calling
import requests
def target_readable(base_url: str, admin_headers: dict, target_user_id: str) -> bool:
r = requests.get(f"{base_url}/user/list", headers=admin_headers, timeout=10)
r.raise_for_status()
return any(u.get("user_id") == target_user_id for u in r.json().get("data", [])) Type guard
def will_v2_lookup_succeed(key_role: str, key_user_id: str | None, target: str | None) -> bool:
# 404 fires when target missing OR not self/admin; caller can only pre-check self/admin
return key_role in ("proxy_admin", "proxy_admin_viewer") or target == key_user_id Try / catch
except requests.HTTPError as e:
if e.response is not None and e.response.status_code == 404:
# means missing OR forbidden - do not leak existence assumptions; surface as 'unavailable'
return None
raise Prevention
- Use admin keys for cross-user lookups; reserve user keys for self-lookup
- Verify ids via /user/list before building links/reports on them
- Remember v2 returns 404 (not 403) for forbidden targets - never parse it as pure existence
When it happens
Trigger: GET /v2/user/info?user_id=X where X was deleted or never existed; or X exists but the caller is neither X itself, a proxy admin/viewer, nor an admin of a team X belongs to.
Common situations: Non-admin dashboards fetching arbitrary users; stale ids after user deletion; access recently lost via team membership changes; assuming team admins can read any team member here without the team link existing.
Understand the failure class
Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.
Related errors
- f"key not allowed to access this user's info. user_id={user_
- LiteLLM Managed File object with id={file_id} not found
- User {user_api_key_dict.user_id} does not have access to vec
- 404
- Skill not found: {skill_id}
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/d6582660009a37b9.
Report an issue: GitHub.