fix(key/info): return 400 instead of 500 when no key is provided

When GET /key/info is called without a ?key= query parameter and the
authenticated principal has no virtual key (e.g. an admin-UI session
token whose UserAPIKeyAuth.api_key is None), info_key_fn passed
hashed_key=None to Prisma find_unique(where={"token": None}), which
raised MissingRequiredValueError and surfaced as an unhandled 500.

Add an explicit None/empty guard that raises a clean 400 ProxyException
before the DB lookup, and add a regression test asserting that prisma
find_unique is never called with token=None.

Fixes #43571

Signed-off-by: apex-mochen <2756823972@qq.com>
This commit is contained in:
apex-mochen 2026-09-29 00:25:31 +08:00
parent f191e08d67
commit 61a745f2b8
2 changed files with 24 additions and 0 deletions

View file

@ -4427,6 +4427,13 @@ async def info_key_fn(
# default to using Auth token if no key is passed in
key = key or user_api_key_dict.api_key
if not key:
raise ProxyException(
message="No key passed in. Pass ?key= or authenticate with a virtual key.",
type=ProxyErrorTypes.bad_request_error,
param="key",
code=status.HTTP_400_BAD_REQUEST,
)
hashed_key: str | None = key
if key is not None:
hashed_key = _hash_token_if_needed(token=key)

View file

@ -6598,6 +6598,23 @@ async def test_info_key_fn_unknown_key_still_404s(monkeypatch):
assert exc_info.value.code == "404"
@pytest.mark.asyncio
async def test_info_key_fn_no_key_returns_400_not_500(monkeypatch):
"""#43571: when both ?key= and auth api_key are None, return a clean 400
instead of letting Prisma raise MissingRequiredValueError as a 500."""
from litellm.proxy.management_endpoints.key_management_endpoints import info_key_fn
mock_prisma_client = AsyncMock()
monkeypatch.setattr("litellm.proxy.proxy_server.prisma_client", mock_prisma_client)
auth = UserAPIKeyAuth(user_role=LitellmUserRoles.PROXY_ADMIN, api_key=None)
with pytest.raises(ProxyException) as exc_info:
await info_key_fn(key=None, user_api_key_dict=auth)
assert exc_info.value.code == "400"
# The prisma find_unique must never be called with token=None
mock_prisma_client.db.litellm_verificationtoken.find_unique.assert_not_called()
@pytest.mark.asyncio
@pytest.mark.parametrize(
("blocked", "expires", "expected_status"),