BerriAI/litellm · error · Exception
OpenMeter: user is required
Error message
OpenMeter: user is required
What it means
When building the CloudEvent for OpenMeter, the logger must resolve a 'subject' (the user the tokens are attributed to). It first takes the request's user field, but only when OPENMETER_TRUST_REQUEST_USER is not 'false' (default is trusted); otherwise it falls back to the user_api_key_user_id bound to the virtual API key in metadata. If both are absent it raises Exception('OpenMeter: user is required'). This exists so OpenMeter metering always has a non-empty subject.
Solutions
- Bind a user to the virtual key used for requests: litellm proxy admin create key with user_id (or update_key with user_id) so metadata.user_api_key_user_id resolves
- Or pass user in the request: litellm.completion(..., user='user-123') / the user field in /chat/completions — works when OPENMETER_TRUST_REQUEST_USER is not 'false'
- If you DO trust request-supplied user values, ensure OPENMETER_TRUST_REQUEST_USER is unset or 'true' so the request user is used
- Audit for master-key or unbound-key traffic before enabling strict mode (OPENMETER_TRUST_REQUEST_USER=false)
Example fix
# before: trust disabled + unbound key -> 'OpenMeter: user is required'
OPENMETER_TRUST_REQUEST_USER=false
# key created without user_id; call has no user field
# after: bind the user to the key
# litellm-admin: curl -X POST /key/generate -d '{"user_id": "user-123", ...}'
OPENMETER_TRUST_REQUEST_USER=false
# or, if request users are trustworthy:
OPENMETER_TRUST_REQUEST_USER=true # and pass user='user-123' on each call Defensive patterns
Strategy: validation
Validate before calling
import os
# Before enabling openmeter logging in strict mode, ensure every key in use carries a user.
trust = os.getenv('OPENMETER_TRUST_REQUEST_USER', 'true').lower() != 'false'
if not trust:
# with trust off, every virtual key issuing traffic MUST have user_id bound
keys_without_user = [k for k in fetch_virtual_keys() if not k.get('user_id')]
assert not keys_without_user, f'bind user_id before strict mode: {keys_without_user}'
# SDK side: always attribute the call
# litellm.completion(model=..., messages=..., user='user-123') Try / catch
try:
litellm.completion(model='gpt-4o', messages=[...], user='user-123')
except Exception as e:
# note: the raise happens in the logging hook; the LLM response may already exist.
if 'OpenMeter: user is required' in str(e):
# fix attribution (bind user_id / pass user) and retry once
... Prevention
- Bind user_id to every virtual key at creation time so attribution never depends on client input
- Wrap SDK calls with a helper that injects user= when the caller omits it
- Before flipping OPENMETER_TRUST_REQUEST_USER to false, audit existing keys for missing user_id
- Monitor proxy logs for the 'user is required' message to catch unattributed traffic early
When it happens
Trigger: Specific paths: (1) OPENMETER_TRUST_REQUEST_USER=false (set for multi-tenant proxies to stop clients forging attribution) while the request's virtual key has no user_id bound — e.g. calls made with the master key or an unbound virtual key; (2) trust enabled (default) but the SDK call omits user= and the key metadata has no user_api_key_user_id. The exception is raised inside log_success_event after every successful LLM call, so it surfaces as a logging-callback failure, not a failed LLM call.
Common situations: Hardening a proxy by setting OPENMETER_TRUST_REQUEST_USER=false without first binding user_id to every virtual key; testing with the sk- master key instead of a virtual key; SDK users calling completion(model=..., messages=...) with no user argument; teams whose keys were created before user attribution was introduced.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Both project_id and topic_id must be provided
- endpoint not set for GenericAPILogger…
- Missing keys= in environment.
- OpenMeter logging error
- 503
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/a52696d19c5a073d.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/integrations/openmeter.py:84
# OPENMETER_TRUST_REQUEST_USER (default "true"): when set to "false",
# the request-supplied `user` field is ignored and the subject is
# resolved solely from the key-bound user_api_key_user_id. Proxies
# serving multi-tenant traffic enable this to prevent clients from
# forging attribution by setting `user` in the request body.
trust_request_user: Final = os.getenv("OPENMETER_TRUST_REQUEST_USER", "true").lower() != "false"
user_param = kwargs.get("user", None) if trust_request_user else None
# If no user provided directly, try to get it from token user_id
if user_param is None:
# Check if user_id is available from the API key metadata
litellm_params: Final = kwargs.get("litellm_params", {})
metadata: Final = litellm_params.get("metadata", {})
user_api_key_user_id: Final = metadata.get("user_api_key_user_id", None)
if user_api_key_user_id is not None:
user_param = user_api_key_user_id
else:
raise Exception("OpenMeter: user is required")
# Ensure subject is always a string for OpenMeter API
subject: Final = str(user_param)
return {
"specversion": "1.0",
"type": os.getenv("OPENMETER_EVENT_TYPE", "litellm_tokens"),
"id": call_id,
"time": dt,
"subject": subject,
"source": "litellm-proxy",
"data": {"model": model, "cost": cost, **usage},
}
def log_success_event(self, kwargs, response_obj, start_time, end_time):
_url = os.getenv("OPENMETER_API_ENDPOINT", "https://openmeter.cloud")
if _url.endswith("/"):
_url += "api/v1/events"View on GitHub (pinned to 77b7c6c40c)