{"record":{"id":"aee0a65d85636d43","repo":"BerriAI/litellm","slug":"user-id-not-found-in-token","errorCode":null,"errorMessage":"User ID not found in token","messagePattern":"User ID not found in token","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"litellm/proxy/management_endpoints/mcp_management_endpoints.py","lineNumber":2054,"sourceCode":"        response_model=MCPUserCredentialResponse,\n    )\n    @management_endpoint_wrapper\n    async def store_mcp_user_credential(\n        server_id: str,\n        payload: MCPUserCredentialRequest,\n        user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),\n    ):\n        \"\"\"Store a BYOK credential for the calling user.\"\"\"\n        prisma_client: Final = get_prisma_client_or_throw(\"Database not connected. Connect a database to your proxy\")\n        mcp_server: Final = await _authorize_and_fetch_mcp_server(prisma_client, user_api_key_dict, server_id)\n        if not getattr(mcp_server, \"is_byok\", False):\n            raise HTTPException(\n                status_code=status.HTTP_400_BAD_REQUEST,\n                detail={\"error\": \"This MCP server does not support BYOK credentials\"},\n            )\n        user_id: Final = user_api_key_dict.user_id or \"\"\n        if not user_id:\n            raise HTTPException(\n                status_code=status.HTTP_400_BAD_REQUEST,\n                detail={\"error\": \"User ID not found in token\"},\n            )\n        if payload.save:\n            await store_user_credential(prisma_client, user_id, server_id, payload.credential)\n            from litellm.proxy._experimental.mcp_server.server import (\n                _invalidate_byok_cred_cache,\n            )\n\n            _invalidate_byok_cred_cache(user_id, server_id)\n            return MCPUserCredentialResponse(server_id=server_id, has_credential=True)\n        # save=False: credential not persisted\n        return MCPUserCredentialResponse(server_id=server_id, has_credential=False)\n\n    @router.delete(\n        \"/server/{server_id}/user-credential\",\n        description=\"Delete the calling user's stored API key for a BYOK MCP server\",\n        dependencies=[Depends(user_api_key_auth)],","sourceCodeStart":2036,"sourceCodeEnd":2072,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/mcp_management_endpoints.py#L2036-L2072","documentation":"Returned (400) by the store-BYOK-credential endpoint when user_api_key_dict.user_id is empty after the server is authorized. The endpoint needs a concrete user to scope the credential to (store_user_credential(prisma_client, user_id, server_id, ...)), so a key that authenticates but is not bound to a user — typically the master key or a bare virtual key — cannot store per-user credentials.","triggerScenarios":"Calling the credential store endpoint with the proxy master key; using a virtual key created without a user binding; service-to-service keys that have role but no user_id.","commonSituations":"Scripts authenticating with LITELLM_MASTER_KEY for everything; keys generated before user assignment policies existed; migrating from shared keys to per-user BYOK without re-issuing keys.","solutions":["Use a key that is bound to a user (create the virtual key with a user / user_id) and retry.","Check the calling key first via /key/info and confirm its user_id is set.","For UI flows, log in as the user so the session token carries the user binding."],"exampleFix":"# before\nrequests.post(f\"{PROXY}/v1/mcp/server/{server_id}/credentials\", headers={\"Authorization\": f\"Bearer {os.environ['LITELLM_MASTER_KEY']}\"}, json=payload)\n\n# after: use a user-bound virtual key\nrequests.post(f\"{PROXY}/v1/mcp/server/{server_id}/credentials\", headers={\"Authorization\": f\"Bearer {USER_VIRTUAL_KEY}\"}, json=payload)","handlingStrategy":"validation","validationCode":"info = requests.get(f\"{PROXY}/key/info\", headers=AUTH, params={\"key\": KEY}).json()\nuser_id = info.get(\"key_info\", info).get(\"user_id\")\nif not user_id:\n    raise ValueError(\"use a virtual key created with user_id for BYOK credential storage\")","typeGuard":"def key_bound_to_user(key_info: dict) -> bool:\n    return bool(key_info.get(\"user_id\"))","tryCatchPattern":"try:\n    store_credential(server_id, payload)\nexcept HTTPError as e:\n    if e.response.status_code == 400 and \"User ID not found\" in e.response.text:\n        raise ValueError(\"switch to the user's own virtual key (it must carry user_id)\")\n    raise","preventionTips":["Never use the master key for per-user endpoints.","Issue virtual keys with an explicit user binding when BYOK is enabled."],"tags":["litellm","mcp","byok","user-id","authentication"],"backgroundTag":"missing-user-id","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}