{"record":{"id":"3b7d443645b95d98","repo":"BerriAI/litellm","slug":"user-id-is-required-either-pass-it-as-a-query-par","errorCode":null,"errorMessage":"user_id is required. Either pass it as a query parameter or authenticate with a user-bound key.","messagePattern":"user_id is required\\. Either pass it as a query parameter or authenticate with a user-bound key\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"litellm/proxy/management_endpoints/internal_user_endpoints.py","lineNumber":1028,"sourceCode":"    from litellm.proxy.proxy_server import prisma_client\n\n    try:\n        if prisma_client is None:\n            raise HTTPException(\n                status_code=500,\n                detail=CommonProxyErrors.db_not_connected_error.value,\n            )\n\n        # Handle URL encoding for + characters\n        if user_id is not None and \" \" in user_id:\n            user_id = get_user_id_from_request(request=request)\n\n        # Default to self-lookup if no user_id provided\n        if user_id is None:\n            user_id = user_api_key_dict.user_id\n\n        if user_id is None:\n            raise HTTPException(\n                status_code=400,\n                detail=\"user_id is required. Either pass it as a query parameter or authenticate with a user-bound key.\",\n            )\n\n        # Check access — returns the user row if allowed, None otherwise.\n        # This avoids a redundant DB fetch since the access check already\n        # loads the target user for team-admin verification.\n        user_row: Final = await _check_user_info_v2_access(\n            user_api_key_dict=user_api_key_dict,\n            target_user_id=user_id,\n        )\n\n        if user_row is None:\n            raise HTTPException(\n                status_code=404,\n                detail=f\"User not found: {user_id}\",\n            )\n","sourceCodeStart":1010,"sourceCodeEnd":1046,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/internal_user_endpoints.py#L1010-L1046","documentation":"GET /v2/user/info defaults user_id to the authenticated key's bound user. If no user_id query param was passed AND the key has no user bound to it (user_api_key_dict.user_id is None - typical for a master key or a team-only virtual key), the endpoint returns 400 telling you to pass user_id or authenticate with a user-bound key.","triggerScenarios":"GET /v2/user/info with no user_id param, authenticated with the master key or a team key generated without a user_id; v1-to-v2 tooling migration using a service key.","commonSituations":"Testing with the master key; keys created for teams (no attached user); CI scripts that assumed the endpoint returns caller info without parameters.","solutions":["Pass ?user_id=<target> explicitly in the request","Use a user-bound virtual key (created via /key/generate with a user_id) for self-lookup","If you need the caller's own id, fetch it from GET /key/info first and pass it as user_id"],"exampleFix":"# before\nGET /v2/user/info  -H 'Authorization: Bearer sk-master-key'   # 400 user_id is required\n\n# after\nGET /v2/user/info?user_id=user123 -H 'Authorization: Bearer sk-master-key'  # 200","handlingStrategy":"validation","validationCode":"import requests\n\ndef resolve_user_id(base_url: str, key: str) -> str | None:\n    r = requests.get(f\"{base_url}/key/info\", params={\"key\": key}, timeout=10)\n    r.raise_for_status()\n    return r.json()[\"info\"].get(\"user_id\")\n\n# before calling /v2/user/info:\nuid = resolve_user_id(BASE, api_key)\nparams = {\"user_id\": uid} if uid else {}  # if still None, the call WILL 400","typeGuard":"function hasResolvedUserId(queryUserId: string | undefined, keyUserId: string | null): boolean {\n  return Boolean(queryUserId ?? keyUserId);\n}","tryCatchPattern":"except requests.HTTPError as e:\n    if e.response is not None and e.response.status_code == 400 and \"user_id is required\" in e.response.text:\n        uid = resolve_user_id(BASE, api_key)\n        if uid is None:\n            raise ValueError(\"use a user-bound key or pass user_id\")\n        return retry_with(params={\"user_id\": uid})\n    raise","preventionTips":["Always pass an explicit user_id to /v2/user/info in service-key scripts","Create user-bound virtual keys for flows that need self-lookup","Resolve the caller's identity once via /key/info and thread it through requests"],"tags":["litellm","user-info","validation","missing-param"],"backgroundTag":"missing-required-parameter","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T10:36:37.832Z"}