{"record":{"id":"441e39dd5eb58c05","repo":"BerriAI/litellm","slug":"you-don-t-have-access-to-this-project","errorCode":null,"errorMessage":"You don't have access to this project","messagePattern":"You don't have access to this project","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py","lineNumber":886,"sourceCode":"                param=\"project_id\",\n            )\n\n        # Check if user has access to this project (admin or team member)\n        is_admin = user_api_key_has_admin_view(user_api_key_dict)\n        is_team_member = False\n\n        if project.team_id and user_api_key_dict.user_id:\n            team = await _team_table(prisma_client).find_unique(where={\"team_id\": project.team_id})\n            if team:\n                caller_user_id = user_api_key_dict.user_id\n                for m in team.members_with_roles or []:\n                    m_user_id = m.get(\"user_id\") if isinstance(m, dict) else getattr(m, \"user_id\", None)\n                    if m_user_id == caller_user_id:\n                        is_team_member = True\n                        break\n\n        if not (is_admin or is_team_member):\n            raise HTTPException(\n                status_code=403,\n                detail={\"error\": \"You don't have access to this project\"},\n            )\n\n        return project\n    except Exception as e:\n        verbose_proxy_logger.exception(\n            \"litellm.proxy.management_endpoints.project_endpoints.project_info(): Exception occured - {}\".format(str(e))\n        )\n        raise handle_exception_on_proxy(e)\n\n\n@router.get(\n    \"/project/list\",\n    tags=[\"project management\"],\n    dependencies=[Depends(user_api_key_auth)],\n    response_model=list[LiteLLM_ProjectTable],\n)","sourceCodeStart":868,"sourceCodeEnd":904,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py#L868-L904","documentation":"Read access on project/info is broader than admin-only: the call passes if user_api_key_has_admin_view is true (proxy admin) OR the caller's user_id appears in the project team's members_with_roles (any membership role, not just admin). Otherwise the endpoint returns 403 'You don't have access to this project'.","triggerScenarios":"GET /project/info with a key whose user is not a proxy admin and not a member of the team stored on the project row — e.g. a user from another team or a key with no user context.","commonSituations":"Multi-tenant dashboards showing all projects to every logged-in user; service keys not tied to a user; users who left or were removed from a team still holding cached links to its projects.","solutions":["Use a proxy admin key for admin-view dashboards that must see every project","Ensure the caller's user is a member of the project's team (add via /team/update) when they legitimately need visibility","Treat 403 here as expected application logic — show a 'no access' state instead of retrying","Verify the key carries a user_id (keys of pure service accounts without users can never pass the member check)"],"exampleFix":"# before (403: user not on the project's team)\nhttpx.get(base + '/project/info', headers=other_team_hdr, params={'project_id': 'p1'})\n\n# after: either add the user to the team, or use an admin key\nhttpx.post(base + '/team/update', headers=admin_hdr, json={'team_id': 'team-a', 'members_with_roles': [{'role': 'member', 'user_id': 'user-9'}]})\nhttpx.get(base + '/project/info', headers=user_9_hdr, params={'project_id': 'p1'})","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    r = httpx.get(base + '/project/info', headers=hdr, params={'project_id': project_id})\n    r.raise_for_status()\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 403 and \"don't have access\" in e.response.text:\n        return render_no_access(project_id)  # expected tenancy boundary: never retry, never leak existence\n    raise","preventionTips":["Use admin-view keys only for dashboards that must enumerate all projects","Filter project lists per user before rendering so unauthorized 403s are rare","Prefer 403 as a deliberate access boundary in UX rather than an error state"],"tags":["litellm","rbac","http-403","teams","projects"],"backgroundTag":"insufficient-permissions","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}