{"record":{"id":"f278e94728b5f0ee","repo":"BerriAI/litellm","slug":"blocked-user-list-must-be-set-as-a-list-filepat","errorCode":null,"errorMessage":"`blocked_user_list` must be set as a list. Filepaths can't be updated.","messagePattern":"`blocked_user_list` must be set as a list\\. Filepaths can't be updated\\.","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"litellm/proxy/management_endpoints/customer_endpoints.py","lineNumber":242,"sourceCode":"                \"error\": \"Blocked user check was never set. This call has no effect.\"\n                + CommonProxyErrors.missing_enterprise_package_docker.value\n            },\n        )\n\n    if (\n        not any(isinstance(x, _ENTERPRISE_BlockedUserList) for x in litellm.callbacks)\n        or litellm.blocked_user_list is None\n    ):\n        raise HTTPException(\n            status_code=400,\n            detail={\"error\": \"Blocked user check was never set. This call has no effect.\"},\n        )\n\n    if isinstance(litellm.blocked_user_list, list):\n        for id in data.user_ids:\n            litellm.blocked_user_list.remove(id)\n    else:\n        raise HTTPException(\n            status_code=500,\n            detail={\"error\": \"`blocked_user_list` must be set as a list. Filepaths can't be updated.\"},\n        )\n\n    return {\"blocked_users\": litellm.blocked_user_list}\n\n\ndef new_budget_request(data: NewCustomerRequest) -> BudgetNewRequest | None:\n    \"\"\"\n    Return a new budget object if new budget params are passed.\n    \"\"\"\n    budget_params: Final = BudgetNewRequest.model_fields.keys()\n    budget_kv_pairs: Final = {}\n\n    # Get the actual values from the data object using getattr\n    for field_name in budget_params:\n        if field_name == \"budget_id\":\n            continue","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/customer_endpoints.py#L224-L260","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nlitellm_settings:\n  blocked_user_list: /etc/litellm/blocked_users.txt\n\n# after\nlitellm_settings:\n  blocked_user_list: [\"user-1\", \"user-2\"]","handlingStrategy":"validation","validationCode":"def unblock_supported_via_api(blocked_user_list: object) -> bool:\n    return isinstance(blocked_user_list, list)","typeGuard":null,"tryCatchPattern":"try:\n    r = httpx.post(f\"{base}/customer/unblock\", json={\"user_ids\": ids}, headers=headers)\n    r.raise_for_status()\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 500 and \"must be set as a list\" in e.response.text:\n        raise RuntimeError(\"blocklist is file-backed; edit the file and reload instead of the API\") from e\n    raise","preventionTips":["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"],"tags":["litellm","blocked-users","configuration","filepath","enterprise"],"backgroundTag":"config-type-mismatch","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}