BerriAI/litellm · error · HTTPException
Only proxy admins can modify user roles.
Error message
Only proxy admins can modify user roles.
What it means
_check_user_update_authz runs for POST /user/update: if the payload sets user_role and the calling key's role is not proxy_admin, LiteLLM returns 403 'Only proxy admins can modify user roles.' Role changes are admin-only so keys cannot escalate privileges. The /user/bulk_update endpoint raises the same message when a bulk payload contains user_role and the caller is not a proxy admin.
Source
Thrown at litellm/proxy/management_endpoints/internal_user_endpoints.py:1261
litellm_changed_by=litellm_changed_by or user_api_key_dict.user_id,
user_api_key_dict=user_api_key_dict,
litellm_proxy_admin_name=litellm_proxy_admin_name,
before_value=(existing_user_row.model_dump_json(exclude_none=True) if existing_user_row else None),
after_value=user_row_typed.model_dump_json(exclude_none=True),
)
)
except Exception as audit_error:
verbose_proxy_logger.warning("Failed to create audit log for user %s: %s", response.get("user_id"), audit_error)
def _check_user_update_authz(
user_request: UpdateUserRequest,
user_api_key_dict: UserAPIKeyAuth,
existing_user_row: BaseModel | None,
) -> None:
"""Authorization checks for /user/update — raises HTTPException on failure."""
if user_request.user_role is not None and user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN.value:
raise HTTPException(status_code=403, detail="Only proxy admins can modify user roles.")
if existing_user_row is not None:
typed_row: Final = LiteLLM_UserTable.model_validate(existing_user_row.model_dump(exclude_none=True))
if not can_user_call_user_update(user_api_key_dict=user_api_key_dict, user_info=typed_row):
raise HTTPException(
status_code=403,
detail={
"error": "User does not have permission to update this user. Only PROXY_ADMIN can update other users."
},
)
elif user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN.value:
# Silent-create guard: only PROXY_ADMIN may create via /user/update.
raise HTTPException(
status_code=404,
detail={
"error": "User not found. Only PROXY_ADMIN can create users via /user/update; use /user/new instead."
},
)View on GitHub (pinned to 77b7c6c40c)
Solutions
- Use a proxy_admin key (master key or admin-bound key) for any payload that includes user_role
- Strip user_role from the payload when a non-admin key only updates profile fields
- Split the flow: non-admin updates profile fields, proxy admin applies the role change separately
Example fix
# before: internal-user key, role included
POST /user/update {"user_id": "u1", "user_alias": "x", "user_role": "proxy_admin"} # 403
# after: non-admin payload without role
POST /user/update {"user_id": "u1", "user_alias": "x"} # 200 Defensive patterns
Strategy: validation
Validate before calling
import requests
def safe_user_update_payload(base_url: str, key: str, payload: dict) -> dict:
if "user_role" in payload:
r = requests.get(f"{base_url}/key/info", params={"key": key}, timeout=10)
r.raise_for_status()
role = r.json()["info"].get("user_role") or "internal_user"
if role != "proxy_admin":
payload = {k: v for k, v in payload.items() if k != "user_role"}
return payload Try / catch
except requests.HTTPError as e:
if e.response is not None and e.response.status_code == 403 and "modify user roles" in e.response.text:
# strip user_role and retry, or escalate to an admin key
... Prevention
- Never round-trip user_role from UI forms into /user/update for non-admins
- Centralize role changes in an admin-only script
- Assert key role via /key/info before sending privileged fields
When it happens
Trigger: POST /user/update with any user_role in the body using an internal_user or team_admin key; POST /user/bulk_update whose user_updates or users entries contain user_role with a non-admin key.
Common situations: Self-service profile flows that forward the whole user object (including user_role) from the client; promotion scripts run with non-admin keys; payloads copied from admin docs.
Related errors
- f"Only proxy admins can create administrative users (proxy_a
- User does not have permission to update this user. Only PROX
- Only admins or team admins can create projects. Your role is
- Only admins or team admins can update projects
- Cannot reassign project to a team you are not an admin of
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/8e019611cdab732c.
Report an issue: GitHub.