BerriAI/litellm · error · Exception

'user' param not passed in. 'enforce_user_param'={general_se

Error message

'user' param not passed in. 'enforce_user_param'={general_settings['enforce_user_param']}

What it means

Raised by _enforce_user_param_check when general_settings.enforce_user_param is true in the proxy config and a POST to an OpenAI LLM route (chat/completions, embeddings, etc., excluding MCP routes) has no user field in the JSON body. Operators enable this flag to force per-end-user spend attribution on shared keys.

Source

Thrown at litellm/proxy/auth/auth_checks.py:524

            project_object=project_object,
            valid_token=valid_token,
            proxy_logging_obj=proxy_logging_obj,
        )


def _enforce_user_param_check(general_settings: dict, request: Request, request_body: dict, route: str) -> None:
    if not general_settings.get("enforce_user_param", False):
        return

    http_method: Final = request.method if hasattr(request, "method") else None
    is_post_method: Final = http_method and http_method.upper() == "POST"
    is_openai_route: Final = RouteChecks.is_llm_api_route(route=route)
    is_mcp_route: Final = route in LiteLLMRoutes.mcp_routes.value or RouteChecks.check_route_access(
        route=route, allowed_routes=LiteLLMRoutes.mcp_routes.value
    )

    if is_post_method and is_openai_route and not is_mcp_route and "user" not in request_body:
        raise Exception(f"'user' param not passed in. 'enforce_user_param'={general_settings['enforce_user_param']}")


def _reject_clientside_metadata_tags_check(general_settings: dict, request_body: dict, route: str) -> None:
    if not general_settings.get("reject_clientside_metadata_tags", False):
        return

    if (
        RouteChecks.is_llm_api_route(route=route)
        and "metadata" in request_body
        and isinstance(request_body["metadata"], dict)
        and "tags" in request_body["metadata"]
    ):
        raise ProxyException(
            message=f"Client-side 'metadata.tags' not allowed in request. 'reject_clientside_metadata_tags'={general_settings['reject_clientside_metadata_tags']}. Tags can only be set via API key metadata.",
            type=ProxyErrorTypes.bad_request_error,
            param="metadata.tags",
            code=status.HTTP_400_BAD_REQUEST,
        )

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Add "user": "<end-user-or-customer-id>" to every completion/embedding request body
  2. If you control the proxy config and do not need forced attribution, set enforce_user_param: false
  3. Centralize the user field in a shared request-builder so no call site can omit it

Example fix

# before
client.chat.completions.create(model="gpt-4o", messages=[...])

# after
client.chat.completions.create(model="gpt-4o", messages=[...], user="user-123")
Defensive patterns

Strategy: validation

Validate before calling

def with_required_user(body: dict, end_user_id: str) -> dict:
    if "user" not in body:
        body["user"] = end_user_id
    return body

payload = with_required_user({"model": "gpt-4o", "messages": messages}, "user-123")

Try / catch

try:
    resp = client.chat.completions.create(**payload)
except Exception as e:
    if "enforce_user_param" in str(e):
        raise ValueError("proxy requires 'user' on every completion call") from e
    raise

Prevention

When it happens

Trigger: Config has general_settings.enforce_user_param: true, then a client POSTs /v1/chat/completions or /v1/embeddings whose body omits "user". MCP routes are exempted, but all standard OpenAI-format completion routes are covered.

Common situations: A platform turns on enforce_user_param to attribute spend to customers, and existing SDK integrations (openai client, LangChain) that never send user start failing; new client code paths forget the field.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/9c4847c1f76a807d. Report an issue: GitHub.