{"record":{"id":"fefb606871e81f1f","repo":"BerriAI/litellm","slug":"str-e-fefb60","errorCode":null,"errorMessage":"str(e)","messagePattern":"str\\(e\\)","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"litellm/proxy/management_endpoints/internal_user_endpoints.py","lineNumber":1662,"sourceCode":"                results.append(\n                    UserUpdateResult(\n                        user_id=user_request.user_id,\n                        user_email=user_request.user_email,\n                        success=False,\n                        error=error_message,\n                    )\n                )\n                failed_updates += 1\n\n        return BulkUpdateUserResponse(\n            results=results,\n            total_requested=len(users_to_update),\n            successful_updates=successful_updates,\n            failed_updates=failed_updates,\n        )\n    except Exception as e:\n        verbose_proxy_logger.exception(\"Failed to update users: %s\", e)\n        raise HTTPException(status_code=500, detail={\"error\": str(e)})\n\n\n@router.post(\n    \"/user/bulk_update\",\n    tags=[\"Internal User management\"],\n    dependencies=[Depends(user_api_key_auth)],\n    response_model=BulkUpdateUserResponse,\n)\n@management_endpoint_wrapper\nasync def bulk_user_update(\n    data: BulkUpdateUserRequest,\n    user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),\n    litellm_changed_by: str | None = Header(\n        None,\n        description=\"The litellm-changed-by header enables tracking of actions performed by authorized users on behalf of other users, providing an audit trail for accountability\",\n    ),\n):\n    \"\"\"","sourceCodeStart":1644,"sourceCodeEnd":1680,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/internal_user_endpoints.py#L1644-L1680","documentation":"bulk_update_processed_users loops users calling the single-user update and records per-item outcomes (successful_updates / failed_updates) in its results array; the outer except is a last resort. Any exception raised outside the per-item loop - a DB connection dropping between items, an error assembling the BulkUpdateUserResponse - becomes HTTP 500 {'error': str(e)}, with the original logged via verbose_proxy_logger.exception('Failed to update users: ...').","triggerScenarios":"A bulk user update where something structural fails mid-run: database disconnect, serialization failure while building the response, or an exception escaping a helper outside the per-item try block in POST /user/bulk_update processing.","commonSituations":"Large bulk jobs hitting transient Postgres drops; monitoring the HTTP status instead of per-item result statuses; re-running a whole batch after a 500 without reconciling which users already succeeded.","solutions":["Inspect server logs - the exception and traceback are logged with 'Failed to update users'","Use the per-item results from any partial response to see which users already succeeded before re-running","If the DB dropped, restore connectivity first (check DATABASE_URL / Postgres health), then retry the remaining users","Chunk large batches so a structural 500 costs less rework"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import requests\n\ndef db_ready(base_url: str, admin_key: str) -> bool:\n    r = requests.get(f\"{base_url}/health/liveliness\",\n                     headers={\"Authorization\": f\"Bearer {admin_key}\"}, timeout=10)\n    return r.ok and r.json().get(\"litellm_database\", \"\") != \"\"","typeGuard":null,"tryCatchPattern":"except requests.HTTPError as e:\n    if e.response is not None and e.response.status_code == 500:\n        # reconcile state first: re-fetch affected users, then retry only the unfinished ones\n        remaining = [u for u in users if not already_applied(u)]\n        return retry_bulk(remaining)","preventionTips":["Treat per-item results in the response body as the source of truth, not the HTTP status","Chunk bulk updates so a structural 500 costs little rework","Verify DB health before starting large bulk jobs"],"tags":["litellm","bulk-update","user-management","database"],"backgroundTag":"internal-server-error","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}