{"record":{"id":"b0f8b15ff899dc46","repo":"BerriAI/litellm","slug":"only-proxy-admin-may-modify-the-organization-role","errorCode":null,"errorMessage":"Only PROXY_ADMIN may modify the organization role of a user who is a global PROXY_ADMIN.","messagePattern":"Only PROXY_ADMIN may modify the organization role of a user who is a global PROXY_ADMIN\\.","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"litellm/proxy/management_endpoints/organization_endpoints.py","lineNumber":1378,"sourceCode":"                },\n            )\n        if existing_organization_membership is None:\n            raise HTTPException(\n                status_code=404,\n                detail={\"error\": f\"Member not found in organization for user_id={data.user_id}\"},\n            )\n\n        # Reject attempts to change the role of a global PROXY_ADMIN via\n        # org-scoped operations. An org-admin of any org could otherwise\n        # alter a PROXY_ADMIN user's per-org role, which has downstream\n        # effects on admin UI filtering and scope derivation.\n        target_user_row = await _table(UserRepository(prisma_client)).find_unique(where={\"user_id\": data.user_id})\n        if target_user_row is not None and getattr(target_user_row, \"user_role\", None) in (\n            LitellmUserRoles.PROXY_ADMIN.value,\n            LitellmUserRoles.PROXY_ADMIN_VIEW_ONLY.value,\n        ):\n            if user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN.value:\n                raise HTTPException(\n                    status_code=403,\n                    detail={\n                        \"error\": (\n                            \"Only PROXY_ADMIN may modify the organization role of a user who is a global PROXY_ADMIN.\"\n                        )\n                    },\n                )\n\n        # Update member role\n        if data.role is not None:\n            await _table(OrganizationMembershipRepository(prisma_client)).update(\n                where={\n                    \"user_id_organization_id\": {\n                        \"user_id\": data.user_id,\n                        \"organization_id\": data.organization_id,\n                    }\n                },\n                data={\"user_role\": data.role},","sourceCodeStart":1360,"sourceCodeEnd":1396,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/organization_endpoints.py#L1360-L1396","documentation":"A privilege-boundary guard: the target user holds the global PROXY_ADMIN role, and the code refuses to let any non-proxy-admin (including org admins) mutate that user's per-organization role, because changing it would corrupt admin UI filtering and scope derivation. The at-fault input is a role-change request aimed at a PROXY_ADMIN user by a lesser-privileged caller.","triggerScenarios":"Thrown at litellm/proxy/management_endpoints/organization_endpoints.py:1378 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Use a PROXY_ADMIN key to modify the organization role of a global PROXY_ADMIN user."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}