mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-24 00:52:24 +00:00
[Fix] handle metadata=null on service-account keys
Addresses Greptile P1: `metadata: null` on a key with a reserved field was crashing inside prepare_metadata_fields because cast(dict, None) is a runtime no-op, so the loop hit `reserved_field in None` and returned 500 instead of 400. Extend the rejection condition to cover `casted_metadata is None`, so attempts to clear an immutable field via `metadata: null` return 400 consistently with the overwrite path. Non-service-account keys still fall through to the existing "clear all metadata" behavior.
This commit is contained in:
parent
01acbb8d3d
commit
208d583a33
2 changed files with 20 additions and 1 deletions
|
|
@ -1523,7 +1523,7 @@ def prepare_metadata_fields(
|
|||
existing_value = existing_metadata.get(reserved_field)
|
||||
if existing_value is None:
|
||||
continue
|
||||
if (
|
||||
if casted_metadata is None or (
|
||||
reserved_field in casted_metadata
|
||||
and casted_metadata[reserved_field] != existing_value
|
||||
):
|
||||
|
|
|
|||
|
|
@ -1300,6 +1300,25 @@ async def test_update_rejects_explicit_null_service_account_id():
|
|||
assert exc_info.value.status_code == 400
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_rejects_whole_metadata_null_on_service_account_key():
|
||||
"""
|
||||
`metadata: null` on a key with a reserved field would have dereferenced None
|
||||
inside the reserved-field loop and returned a 500. Must surface as a 400
|
||||
since the effect would be to clear an immutable field.
|
||||
"""
|
||||
data = UpdateKeyRequest(key="sk-1", metadata=None, team_id="IJ")
|
||||
existing_key = LiteLLM_VerificationToken(
|
||||
token="hashed",
|
||||
team_id="IJ",
|
||||
metadata={"service_account_id": "sa-123"},
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
await prepare_key_update_data(data=data, existing_key_row=existing_key)
|
||||
assert exc_info.value.status_code == 400
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_without_metadata_still_preserves_existing():
|
||||
"""Omitting metadata entirely must not drop existing metadata fields."""
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue