BerriAI/litellm · error · HTTPException
Cannot reassign project to a team you are not an admin of
Error message
Cannot reassign project to a team you are not an admin of
What it means
Reassigning a project to a different team (data.team_id != existing_project.team_id) requires, in addition to edit rights on the current team, admin rights on the DESTINATION team — checked via _check_user_permission_for_project against the validated target team object. Without it, HTTP 403. This stops a team admin from dumping projects into another team's namespace.
Source
Thrown at enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py:607
raise HTTPException(
status_code=403,
detail={"error": "Only admins or team admins can update projects"},
)
# Reassigning to a different team also requires admin rights on the
# destination team — otherwise a team admin could shed projects into
# an unsuspecting team's namespace.
if data.team_id is not None and data.team_id != existing_project.team_id:
can_assign_to_target = await _check_user_permission_for_project(
user_api_key_dict=user_api_key_dict,
team_id=data.team_id,
prisma_client=prisma_client,
team_object=(
LiteLLM_TeamTable.model_validate(target_team_obj.model_dump()) if target_team_obj else None
),
)
if not can_assign_to_target:
raise HTTPException(
status_code=403,
detail={"error": "Cannot reassign project to a team you are not an admin of"},
)
# Validate project limits against team limits
if target_team_obj is not None:
_check_team_project_limits(
team_object=LiteLLM_TeamTable.model_validate(target_team_obj.model_dump()),
data=data,
)
# Prepare update data
update_data = data.json(exclude_none=True, exclude={"project_id"})
update_data = prisma_client.jsonify_object(update_data)
update_data["updated_by"] = user_api_key_dict.user_id or litellm_proxy_admin_name
# Handle budget updates
budget_fields = LiteLLM_BudgetTable.model_fields.keys()View on GitHub (pinned to 6c2dcb801b)
Solutions
- Have a proxy admin or an admin of the destination team perform the reassignment
- Add the caller as an admin of the destination team first, then retry
- Alternatively, create a new project under the destination team and migrate keys/members deliberately
Example fix
# before (caller not admin of team B)
curl -H 'Authorization: Bearer sk-teamA-admin' -X PUT .../project/update -d '{"project_id":"p1","team_id":"team-B"}'
# after (proxy admin key)
curl -H 'Authorization: Bearer sk-admin' -X PUT .../project/update -d '{"project_id":"p1","team_id":"team-B"}' Defensive patterns
Strategy: validation
Validate before calling
proj = await client.get(f'/project/info?project_id={pid}')
current_team = proj.project.team_id
if new_team := payload.get('team_id'):
if new_team != current_team and my_role != 'proxy_admin':
team = await client.get(f'/team/info?team_id={new_team}')
admins = [m['user_id'] for m in (team.teams[0].members_with_roles or []) if m.get('role') == 'admin']
if me.user_id not in admins:
raise PermissionError('Caller is not an admin of the destination team') Type guard
const canReassign = (myRole, myUserId, currentTeamId, targetTeamId, targetTeam) => targetTeamId === undefined || targetTeamId === currentTeamId || myRole === 'proxy_admin' || (targetTeam.members_with_roles ?? []).some((m) => m.user_id === myUserId && m.role === 'admin');
Prevention
- Treat team reassignment as a two-admin workflow: confirm destination-team admin involvement
- Record intended team ownership in your CMDB and validate moves before executing them
When it happens
Trigger: PUT /project/update including a team_id different from the project's current team, where the caller is not a proxy admin and not an admin of the destination team.
Common situations: Org restructures moving projects between teams, team admins 'handing off' a project without coordinating the receiving team's admins.
Related errors
- Only admins or team admins can update projects
- Only admins or team admins can create projects. Your role is
- An error occurred: {str(e)}, banned_keywords_list={banned_ke
- Model '{m}' not in team's allowed models. Team allowed model
- Project max_budget ({data.max_budget}) exceeds team's max_bu
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/050884f58a86983e.
Report an issue: GitHub.