BerriAI/litellm · error · HTTPException
str(e)
Error message
str(e)
What it means
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: ...').
Source
Thrown at litellm/proxy/management_endpoints/internal_user_endpoints.py:1662
results.append(
UserUpdateResult(
user_id=user_request.user_id,
user_email=user_request.user_email,
success=False,
error=error_message,
)
)
failed_updates += 1
return BulkUpdateUserResponse(
results=results,
total_requested=len(users_to_update),
successful_updates=successful_updates,
failed_updates=failed_updates,
)
except Exception as e:
verbose_proxy_logger.exception("Failed to update users: %s", e)
raise HTTPException(status_code=500, detail={"error": str(e)})
@router.post(
"/user/bulk_update",
tags=["Internal User management"],
dependencies=[Depends(user_api_key_auth)],
response_model=BulkUpdateUserResponse,
)
@management_endpoint_wrapper
async def bulk_user_update(
data: BulkUpdateUserRequest,
user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
litellm_changed_by: str | None = Header(
None,
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",
),
):
"""View on GitHub (pinned to 77b7c6c40c)
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
Defensive patterns
Strategy: retry
Validate before calling
import requests
def db_ready(base_url: str, admin_key: str) -> bool:
r = requests.get(f"{base_url}/health/liveliness",
headers={"Authorization": f"Bearer {admin_key}"}, timeout=10)
return r.ok and r.json().get("litellm_database", "") != "" Try / catch
except requests.HTTPError as e:
if e.response is not None and e.response.status_code == 500:
# reconcile state first: re-fetch affected users, then retry only the unfinished ones
remaining = [u for u in users if not already_applied(u)]
return retry_bulk(remaining) Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Not connected to DB!
- Failed to update user
- Database not connected
- DB not connected. This endpoint needs a database; set DATABA
- DB not connected. This endpoint needs a database; set DATABA
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/fefb606871e81f1f.
Report an issue: GitHub.