{"record":{"id":"3ac3676ee89b8531","repo":"BerriAI/litellm","slug":"malformed-request-no-keys-passed-in","errorCode":null,"errorMessage":"Malformed request. No keys passed in.","messagePattern":"Malformed request\\. No keys passed in\\.","errorType":"http","errorClass":"HTTPException","httpStatus":422,"severity":"warning","filePath":"litellm/proxy/management_endpoints/key_management_endpoints.py","lineNumber":3554,"sourceCode":"    Returns:\n        Dict containing the key and its associated information\n\n    Example Curl:\n    ```\n    curl -X GET \"http://0.0.0.0:4000/key/info\" \\\n    -H \"Authorization: Bearer sk-1234\" \\\n    -d {\"keys\": [\"sk-1\", \"sk-2\", \"sk-3\"]}\n    ```\n    \"\"\"\n    from litellm.proxy.proxy_server import prisma_client, user_api_key_cache\n\n    try:\n        if prisma_client is None:\n            raise Exception(\n                \"Database not connected. Connect a database to your proxy - https://docs.litellm.ai/docs/simple_proxy#managing-auth---virtual-keys\"\n            )\n        if data is None:\n            raise HTTPException(\n                status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,\n                detail={\"message\": \"Malformed request. No keys passed in.\"},\n            )\n\n        # Resolve key_aliases to tokens so we never pass token=None (unbounded query)\n        tokens_to_query: Final = list(data.keys) if data.keys else []\n        if data.key_aliases:\n            alias_rows: Final = await _prisma_table(VerificationTokenRepository(prisma_client)).find_many(\n                where={\"key_alias\": {\"in\": data.key_aliases}},\n                include={\"litellm_budget_table\": True},\n            )\n            alias_tokens: Final = [row.token for row in alias_rows if row.token]\n            tokens_to_query.extend(alias_tokens)\n\n        if not tokens_to_query:\n            return {\"key\": data.keys, \"info\": []}\n\n        key_info: Final = await prisma_client.get_data(token=tokens_to_query, table_name=\"key\", query_type=\"find_all\")","sourceCodeStart":3536,"sourceCodeEnd":3572,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/key_management_endpoints.py#L3536-L3572","documentation":"POST /v2/key/info requires a KeyRequest body containing keys (and/or key_aliases) to look up. When the parsed body is None — request posted with no JSON body at all, or a body FastAPI could not bind — the handler explicitly returns 422 'Malformed request. No keys passed in.' rather than querying with an unbounded (token=None) filter.","triggerScenarios":"POST /v2/key/info with no body, an empty JSON object, or a Content-Type that doesn't parse as JSON; client code conditionally omitting the keys field and serializing {}.","commonSituations":"A 'get info for selected keys' feature where none are selected; forgetting -d/--data in curl; sending the keys as query params instead of the JSON body; upstream proxy/load balancer stripping the request body.","solutions":["Send a JSON body: {\"keys\": [\"sk-1\", \"sk-2\"]} (or key_aliases).","Ensure Content-Type: application/json is set by your client.","Short-circuit your calling code when the key list is empty instead of issuing the request."],"exampleFix":"# before\nclient.post(\"/v2/key/info\")\n\n# after\nclient.post(\"/v2/key/info\", json={\"keys\": [\"sk-1\", \"sk-2\"]})","handlingStrategy":"validation","validationCode":"def build_key_info_body(keys: list[str] | None, key_aliases: list[str] | None) -> dict:\n    if not keys and not key_aliases:\n        raise ValueError(\"/v2/key/info needs non-empty 'keys' or 'key_aliases'\")\n    body: dict = {}\n    if keys:\n        body[\"keys\"] = keys\n    if key_aliases:\n        body[\"key_aliases\"] = key_aliases\n    return body","typeGuard":"def is_valid_key_info_request(keys: list[str] | None, key_aliases: list[str] | None) -> bool:\n    return bool(keys) or bool(key_aliases)","tryCatchPattern":null,"preventionTips":["Always send a JSON body with Content-Type: application/json on /v2/key/info.","Short-circuit empty selections client-side before making the request.","Assert a parseable body survives any intermediary proxy/load balancer in staging tests."],"tags":["validation","required-field","key-management","litellm-proxy"],"backgroundTag":"request-validation-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}