{"record":{"id":"11bf63cd3546eb43","repo":"BerriAI/litellm","slug":"user-id-is-required-passed-user-id-data-user-i","errorCode":null,"errorMessage":"user_id is required, passed user_id = {data.user_id}","messagePattern":"user_id is required, passed user_id = (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":500,"severity":"error","filePath":"litellm/proxy/management_endpoints/customer_endpoints.py","lineNumber":724,"sourceCode":"            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\"],\n    dependencies=[Depends(user_api_key_auth)],\n    response_model=DeleteCustomersResponse,\n)\n@router.post(\n    \"/end_user/delete\",\n    tags=[\"Customer Management\"],\n    include_in_schema=False,","sourceCodeStart":706,"sourceCodeEnd":742,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/customer_endpoints.py#L706-L742","documentation":"POST /customer/update requires a non-empty user_id; when it is None or '' the endpoint raises ValueError('user_id is required, passed user_id = ...') which handle_exception_on_proxy surfaces as HTTP 500. Note it is a 500, not a 422, despite being purely a client payload problem.","triggerScenarios":"POST /customer/update omitting user_id from the JSON body, sending null, or sending an empty string.","commonSituations":"Partial-update clients that only send changed fields; pydantic/TypedDict models defaulting user_id to None; JSON key typos like userId that silently drop the field.","solutions":["Always include a non-empty user_id in the update body","Validate the payload client-side with a required-user_id schema before sending","Treat this 500 as a client payload bug in monitoring - it is not a proxy outage"],"exampleFix":"# before\nresp = httpx.post(f\"{base}/customer/update\", json={\"blocked\": True}, headers=headers)   # no user_id -> 500\n\n# after\nresp = httpx.post(f\"{base}/customer/update\", json={\"user_id\": \"cust-42\", \"blocked\": True}, headers=headers)","handlingStrategy":"validation","validationCode":"def has_required_user_id(payload: dict) -> bool:\n    uid = payload.get(\"user_id\")\n    return isinstance(uid, str) and len(uid.strip()) > 0","typeGuard":"from typing import TypeGuard\n\n\ndef is_valid_update_payload(payload: dict) -> TypeGuard[dict]:\n    \"\"\"Narrows to payloads safe to send to POST /customer/update.\"\"\"\n    uid = payload.get(\"user_id\")\n    return isinstance(uid, str) and len(uid.strip()) > 0","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 \"user_id is required\" in e.response.text:\n        raise ValueError(\"update payload must include a non-empty user_id\") from e\n    raise","preventionTips":["Type update payloads with user_id as a required str field (pydantic or TypeGuard)","Lint outgoing payloads in shared API clients so empty user_id never reaches the wire","Remember this route 500s on bad input - map it to a client error in dashboards, not server alerts"],"tags":["litellm","required-field","validation","customer-management","http-500"],"backgroundTag":"missing-required-argument","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}