BerriAI/litellm · error · ValueError
Failed updating customer data. User ID does not exist passed
Error message
Failed updating customer data. User ID does not exist passed user_id={data.user_id} What it means
POST /customer/update writes with where={"user_id": data.user_id} and expects Prisma's update to return the updated record. If no row matches - commonly because the code also assigns data.user_id into the update payload, so sending a NEW id as user_id matches nothing - update returns None and the endpoint raises ValueError('Failed updating customer data...'), which handle_exception_on_proxy converts to HTTP 500.
Source
Thrown at litellm/proxy/management_endpoints/customer_endpoints.py:717
# Ensure object_permission is not in the update data
# It should have been converted to object_permission_id by handle_update_object_permission_common
if "object_permission" in update_end_user_table_data:
verbose_proxy_logger.warning(
"object_permission still in update_end_user_table_data: %s",
update_end_user_table_data.get("object_permission"),
)
update_end_user_table_data.pop("object_permission", None)
if data.user_id is not None and len(data.user_id) > 0:
update_end_user_table_data["user_id"] = data.user_id
verbose_proxy_logger.debug("In update customer, user_id condition block.")
response: Final = await _typed_table(EndUserRepository(prisma_client)).update(
where={"user_id": data.user_id},
data=update_end_user_table_data,
include={"litellm_budget_table": True, "object_permission": True},
)
if response is None:
raise ValueError(f"Failed updating customer data. User ID does not exist passed user_id={data.user_id}")
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_id,)))
return _to_customer_response(response)
else:
raise ValueError(f"user_id is required, passed user_id = {data.user_id}")
# update based on remaining passed in values
except Exception as e:
verbose_proxy_logger.exception("litellm.proxy.proxy_server.update_end_user(): Exception occured - %s", e)
raise handle_exception_on_proxy(e)
@router.post(
"/customer/delete",
tags=["Customer Management"],View on GitHub (pinned to 77b7c6c40c)
Solutions
- Send the EXISTING user_id in the request body; confirm it with GET /customer/info first
- To change a customer's id: create the new customer, migrate references, delete the old one
- Treat this 500 as a not-found signal in callers - it indicates no row matched, not a server outage
Example fix
# before
resp = update_customer({"user_id": "renamed-id", "blocked": True}) # no row with "renamed-id" -> 500
# after
resp = update_customer({"user_id": "original-id", "blocked": True}) # existing row updated Defensive patterns
Strategy: validation
Validate before calling
import httpx
def safe_update(base: str, headers: dict, payload: dict) -> dict:
uid = payload["user_id"]
if httpx.get(f"{base}/customer/info", params={"end_user_id": uid}, headers=headers).status_code != 200:
raise KeyError(f"customer {uid!r} does not exist; update would 500")
r = httpx.post(f"{base}/customer/update", json=payload, headers=headers)
r.raise_for_status()
return r.json() Try / catch
try:
r = httpx.post(f"{base}/customer/update", json=payload, headers=headers)
except httpx.HTTPStatusError as e:
if e.response.status_code == 500 and "Failed updating customer data" in e.response.text:
raise LookupError(f"no customer with user_id={payload['user_id']!r}") from e
raise Prevention
- Verify the customer exists immediately before updating to avoid the None-response ValueError path
- Never use /customer/update to rename a customer id
- Re-check for concurrent deletions if updates run alongside cleanup jobs
When it happens
Trigger: POST /customer/update with a user_id that has no existing row: typically a rename attempt passing the new id, or the customer was deleted concurrently before the update landed.
Common situations: Teams try to change a customer's identifier through update and hit this because the where-clause uses the same new id; races where another process deletes the customer between read and write; whitespace-normalized ids that no longer match stored values.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- End User Id={data.user_id} does not exist in db
- DB not connected. This endpoint needs a database; set DATABA
- Postgres DB Not connected
- {e}
- End User Id={end_user_id} does not exist in db
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/1b9caf40b1a53788.
Report an issue: GitHub.