BerriAI/litellm · error · HTTPException
`blocked_user_list` must be set as a list. Filepaths can't b
Error message
`blocked_user_list` must be set as a list. Filepaths can't be updated.
What it means
litellm.blocked_user_list can be either a Python list of user ids or a path to a file of ids. POST /customer/unblock only supports the list form - it calls list.remove() per id - so when the blocklist was loaded from a filepath string the endpoint refuses with HTTP 500: backtick-blocked_user_listbacktick must be set as a list, filepaths cannot be updated.
Source
Thrown at litellm/proxy/management_endpoints/customer_endpoints.py:242
"error": "Blocked user check was never set. This call has no effect."
+ CommonProxyErrors.missing_enterprise_package_docker.value
},
)
if (
not any(isinstance(x, _ENTERPRISE_BlockedUserList) for x in litellm.callbacks)
or litellm.blocked_user_list is None
):
raise HTTPException(
status_code=400,
detail={"error": "Blocked user check was never set. This call has no effect."},
)
if isinstance(litellm.blocked_user_list, list):
for id in data.user_ids:
litellm.blocked_user_list.remove(id)
else:
raise HTTPException(
status_code=500,
detail={"error": "`blocked_user_list` must be set as a list. Filepaths can't be updated."},
)
return {"blocked_users": litellm.blocked_user_list}
def new_budget_request(data: NewCustomerRequest) -> BudgetNewRequest | None:
"""
Return a new budget object if new budget params are passed.
"""
budget_params: Final = BudgetNewRequest.model_fields.keys()
budget_kv_pairs: Final = {}
# Get the actual values from the data object using getattr
for field_name in budget_params:
if field_name == "budget_id":
continueView on GitHub (pinned to 77b7c6c40c)
Solutions
- Switch the proxy to a list-based blocked_user_list in config.yaml and restart, then use the API
- Or edit the file directly (remove the id) and restart/reload the proxy - the API cannot mutate files
- Standardize on one workflow: file-based (manual edits) or list-based (API), never mixed
Example fix
# before litellm_settings: blocked_user_list: /etc/litellm/blocked_users.txt # after litellm_settings: blocked_user_list: ["user-1", "user-2"]
Defensive patterns
Strategy: validation
Validate before calling
def unblock_supported_via_api(blocked_user_list: object) -> bool:
return isinstance(blocked_user_list, list) Try / catch
try:
r = httpx.post(f"{base}/customer/unblock", json={"user_ids": ids}, headers=headers)
r.raise_for_status()
except httpx.HTTPStatusError as e:
if e.response.status_code == 500 and "must be set as a list" in e.response.text:
raise RuntimeError("blocklist is file-backed; edit the file and reload instead of the API") from e
raise Prevention
- If you plan to manage blocks via API, configure blocked_user_list as a list from day one
- Document which deployments use file-backed lists so operators do not attempt API unblocks on them
- Put file-backed lists under version control so manual unblocks are auditable
When it happens
Trigger: Configuring litellm_settings.blocked_user_list: "/etc/litellm/blocked_users.txt" (any string path) and then calling POST /customer/unblock to remove ids via the API.
Common situations: Large orgs load big blocklists from files for manageability, then admins try to unblock individual users via the API; enterprise UI uploads can also land as file-backed lists.
Related errors
- Blocked user check was never set. This call has no effect.
- custom_ui_sso_sign_in_handler is not configured. Please set
- Trying to use Blocked User ListThis uses the enterprise fold
- Trying to use ENTERPRISE BlockedUserYou must be a LiteLLM En
- Blocked user check was never set. This call has no effect.Th
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/f278e94728b5f0ee.
Report an issue: GitHub.