BerriAI/litellm · error · ValueError
user_id is required, passed user_id = {data.user_ids}
Error message
user_id is required, passed user_id = {data.user_ids} What it means
POST /customer/delete requires user_ids to be a non-empty list; otherwise the endpoint raises ValueError (note the message says 'user_id' although the field is user_ids), which handle_exception_on_proxy converts to HTTP 500. Like the update route, a client payload mistake surfaces as a server error code.
Source
Thrown at litellm/proxy/management_endpoints/customer_endpoints.py:803
type="not_found",
code=404,
param="user_ids",
)
# All users exist, proceed with deletion
response: Final = await _typed_table(EndUserRepository(prisma_client)).delete_many(
where={"user_id": {"in": data.user_ids}}
)
verbose_proxy_logger.debug("received response from updating prisma client. response=%s", response)
await _evict_end_user_cache_keys(_end_user_cache_keys(data.user_ids))
return DeleteCustomersResponse(
deleted_customers=response,
message="Successfully deleted customers with ids: " + str(data.user_ids),
)
else:
raise ValueError(f"user_id is required, passed user_id = {data.user_ids}")
# update based on remaining passed in values
except Exception as e:
verbose_proxy_logger.error("litellm.proxy.proxy_server.delete_end_user(): Exception occured - %s", e)
raise handle_exception_on_proxy(e)
@router.get(
"/customer/list",
tags=["Customer Management"],
dependencies=[Depends(user_api_key_auth)],
response_model=list[CustomerResponse],
)
@router.get(
"/end_user/list",
tags=["Customer Management"],
include_in_schema=False,
dependencies=[Depends(user_api_key_auth)],View on GitHub (pinned to 77b7c6c40c)
Solutions
- Skip the API call entirely when the candidate list is empty
- Require a non-empty user_ids array in the request-building code
- Classify this 500 as a client payload bug, not a proxy fault
Example fix
# before
resp = post("/customer/delete", {"user_ids": []}) # -> 500 ValueError via handler
# after
if ids:
resp = post("/customer/delete", {"user_ids": ids}) Defensive patterns
Strategy: validation
Validate before calling
def delete_payload_valid(payload: dict) -> bool:
ids = payload.get("user_ids")
return isinstance(ids, list) and len(ids) > 0 Type guard
from typing import TypeGuard
def has_non_empty_user_ids(payload: dict) -> TypeGuard[dict]:
"""Narrows to payloads safe to send to POST /customer/delete."""
ids = payload.get("user_ids")
return isinstance(ids, list) and len(ids) > 0 and all(isinstance(i, str) and i for i in ids) Try / catch
try:
r = httpx.post(f"{base}/customer/delete", json=payload, headers=headers)
except httpx.HTTPStatusError as e:
if e.response.status_code == 500 and "user_id is required" in e.response.text:
raise ValueError("delete payload must include a non-empty user_ids list") from e
raise Prevention
- Guard empty batches before calling the API - an empty delete is a no-op anyway
- Use a TypeGuard or pydantic model with min_length=1 on user_ids
- Remember the error text says 'user_id' but the field is 'user_ids' - do not chase the wrong key
When it happens
Trigger: POST /customer/delete with user_ids omitted, null, or an empty array [] in the JSON body.
Common situations: Templated scripts rendering an empty list when no candidates matched; cleanup loops that still issue the API call when the filtered set is empty; misconfigured JSON payloads using a different key name.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- user_id is required, passed user_id = {data.user_id}
- {e}
- No models configured on proxy
- Default Model not on proxy. Configure via `/model/new` or co
- Not connected to DB!
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/9d64644e447feb64.
Report an issue: GitHub.