{"record":{"id":"feb68cbd01a558e4","repo":"BerriAI/litellm","slug":"only-admins-or-team-admins-can-create-projects-yo","errorCode":null,"errorMessage":"Only admins or team admins can create projects. Your role is {user_api_key_dict.user_role}","messagePattern":"Only admins or team admins can create projects\\. Your role is (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py","lineNumber":387,"sourceCode":"        team_object = await _validate_team_exists(team_id=data.team_id, prisma_client=prisma_client)\n\n        # Validate project limits against team limits\n        _check_team_project_limits(\n            team_object=LiteLLM_TeamTable.model_validate(team_object.model_dump()),\n            data=data,\n        )\n\n        # Check if user has permission to create projects for this team\n        # only team admins can create projects for their team\n        has_permission = await _check_user_permission_for_project(\n            user_api_key_dict=user_api_key_dict,\n            team_id=data.team_id,\n            prisma_client=prisma_client,\n            team_object=LiteLLM_TeamTable.model_validate(team_object.model_dump()),\n        )\n\n        if not has_permission:\n            raise HTTPException(\n                status_code=403,\n                detail={\n                    \"error\": f\"Only admins or team admins can create projects. Your role is {user_api_key_dict.user_role}\"\n                },\n            )\n\n        # Generate project_id if not provided\n        if data.project_id is None:\n            data.project_id = str(uuid.uuid4())\n        else:\n            # Check if project_id already exists\n            existing_project = await prisma_client.db.litellm_projecttable.find_unique(\n                where={\"project_id\": data.project_id}\n            )\n            if existing_project is not None:\n                raise ProxyException(\n                    message=f\"Project id = {data.project_id} already exists. Please use a different project id.\",\n                    type=\"bad_request\",","sourceCodeStart":369,"sourceCodeEnd":405,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py#L369-L405","documentation":"POST /project/new authorizes via _check_user_permission_for_project: only proxy admins or admins of the specific target team may create projects for it. If the caller's role/team membership does not satisfy this, the proxy returns HTTP 403 including the caller's actual role. This prevents a team admin from creating projects under another team's namespace.","triggerScenarios":"Calling POST /project/new with a virtual key whose user is a member (not admin) of data.team_id, or an internal-user key with no team affiliation, e.g. role 'internal_user' targeting a team they do not administer.","commonSituations":"A team member with an own-api-key trying to self-provision a project, service accounts without admin grants, or an org_admin key targeting a team outside their scope.","solutions":["Have a proxy admin or the target team's admin perform the creation (or use an admin key)","Add the user as an admin of the team (PUT /team/update with the user in team_admin list / admin role) and retry","If the caller should be a proxy admin, issue the key from an admin user or use the master key"],"exampleFix":"# before (member-level key)\ncurl -H 'Authorization: Bearer sk-member-key' -X POST .../project/new -d '{\"team_id\":\"t1\",...}'\n# after (admin key)\ncurl -H 'Authorization: Bearer sk-admin-key' -X POST .../project/new -d '{\"team_id\":\"t1\",...}'","handlingStrategy":"validation","validationCode":"# Verify caller's role/team-admin status before attempting creation\nme = await client.get('/user/info')\nif not me.user_info.get('user_role') in ('proxy_admin', 'proxy_admin_viewer'):\n    team = await client.get(f'/team/info?team_id={team_id}')\n    admins = [m['user_id'] for m in (team.teams[0].members_with_roles or []) if m.get('role') == 'admin']\n    if me.user_id not in admins:\n        raise PermissionError('Caller cannot create projects for this team')","typeGuard":"const canCreateProject = (userRole, userId, team) =>\n  userRole === 'proxy_admin' ||\n  (team.members_with_roles ?? []).some(\n    (m) => m.user_id === userId && m.role === 'admin'\n  );","tryCatchPattern":"catch (e) {\n  if (e.status === 403 && /Only admins or team admins can create projects/.test(e.body?.detail?.error ?? '')) {\n    throw new Error(`Permission denied (role=${myRole}); ask a proxy/team admin to create the project`);\n  }\n  throw e;\n}","preventionTips":["Run provisioning automation with a dedicated proxy-admin service key","Keep team admin lists in sync with the people running project automation"],"tags":["litellm","authorization","rbac","team","http-403"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}