{"record":{"id":"1b9caf40b1a53788","repo":"BerriAI/litellm","slug":"failed-updating-customer-data-user-id-does-not-ex","errorCode":null,"errorMessage":"Failed updating customer data. User ID does not exist passed user_id={data.user_id}","messagePattern":"Failed updating customer data\\. User ID does not exist passed user_id=(.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":500,"severity":"error","filePath":"litellm/proxy/management_endpoints/customer_endpoints.py","lineNumber":717,"sourceCode":"        # Ensure object_permission is not in the update data\n        # It should have been converted to object_permission_id by handle_update_object_permission_common\n        if \"object_permission\" in update_end_user_table_data:\n            verbose_proxy_logger.warning(\n                \"object_permission still in update_end_user_table_data: %s\",\n                update_end_user_table_data.get(\"object_permission\"),\n            )\n            update_end_user_table_data.pop(\"object_permission\", None)\n\n        if data.user_id is not None and len(data.user_id) > 0:\n            update_end_user_table_data[\"user_id\"] = data.user_id\n            verbose_proxy_logger.debug(\"In update customer, user_id condition block.\")\n            response: Final = await _typed_table(EndUserRepository(prisma_client)).update(\n                where={\"user_id\": data.user_id},\n                data=update_end_user_table_data,\n                include={\"litellm_budget_table\": True, \"object_permission\": True},\n            )\n            if response is None:\n                raise ValueError(f\"Failed updating customer data. User ID does not exist passed user_id={data.user_id}\")\n            verbose_proxy_logger.debug(\"received response from updating prisma client. response=%s\", response)\n\n            await _evict_end_user_cache_keys(_end_user_cache_keys((data.user_id,)))\n\n            return _to_customer_response(response)\n        else:\n            raise ValueError(f\"user_id is required, passed user_id = {data.user_id}\")\n\n        # update based on remaining passed in values\n\n    except Exception as e:\n        verbose_proxy_logger.exception(\"litellm.proxy.proxy_server.update_end_user(): Exception occured - %s\", e)\n        raise handle_exception_on_proxy(e)\n\n\n@router.post(\n    \"/customer/delete\",\n    tags=[\"Customer Management\"],","sourceCodeStart":699,"sourceCodeEnd":735,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/customer_endpoints.py#L699-L735","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nresp = update_customer({\"user_id\": \"renamed-id\", \"blocked\": True})   # no row with \"renamed-id\" -> 500\n\n# after\nresp = update_customer({\"user_id\": \"original-id\", \"blocked\": True})  # existing row updated","handlingStrategy":"validation","validationCode":"import httpx\n\n\ndef safe_update(base: str, headers: dict, payload: dict) -> dict:\n    uid = payload[\"user_id\"]\n    if httpx.get(f\"{base}/customer/info\", params={\"end_user_id\": uid}, headers=headers).status_code != 200:\n        raise KeyError(f\"customer {uid!r} does not exist; update would 500\")\n    r = httpx.post(f\"{base}/customer/update\", json=payload, headers=headers)\n    r.raise_for_status()\n    return r.json()","typeGuard":null,"tryCatchPattern":"try:\n    r = httpx.post(f\"{base}/customer/update\", json=payload, headers=headers)\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 500 and \"Failed updating customer data\" in e.response.text:\n        raise LookupError(f\"no customer with user_id={payload['user_id']!r}\") from e\n    raise","preventionTips":["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"],"tags":["litellm","not-found","customer-management","http-500","rename","prisma"],"backgroundTag":"resource-not-found","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}