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

  1. Have a proxy admin or an admin of the destination team perform the reassignment
  2. Add the caller as an admin of the destination team first, then retry
  3. 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

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


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/050884f58a86983e. Report an issue: GitHub.