BerriAI/litellm · error · Exception
OpenMeter logging error
Error message
OpenMeter logging error: {e.response.text} What it means
In the synchronous log_success_event, OpenMeterLogger POSTs a CloudEvents JSON payload to {OPENMETER_API_ENDPOINT}/api/v1/events with a Bearer token from OPENMETER_API_KEY. When the HTTP layer raises httpx.HTTPStatusError (non-2xx response), it is re-raised as a generic Exception prefixed 'OpenMeter logging error:' plus the response body text, so the actual status code and server message are embedded in the string.
Solutions
- Read the embedded response text in the exception — it carries the server's actual error (invalid token, not found, etc.) and points at the fix
- Verify OPENMETER_API_KEY is valid and current (curl -H 'Authorization: Bearer <key>' <endpoint>/api/v1/events with a test CloudEvent)
- Fix OPENMETER_API_ENDPOINT to be the base URL only (e.g. https://openmeter.cloud); the code appends api/v1/events itself — remove any duplicated path
- If the text shows 5xx or timeouts, check OpenMeter status / retry later — logging failures surface in proxy logs while LLM traffic itself is unaffected
Example fix
# before (doubled path -> 404) OPENMETER_API_ENDPOINT=https://openmeter.cloud/api/v1/events # after (base URL only; code appends /api/v1/events) OPENMETER_API_ENDPOINT=https://openmeter.cloud
Defensive patterns
Strategy: try-catch
Validate before calling
import os, httpx, json, datetime
base = os.getenv('OPENMETER_API_ENDPOINT', 'https://openmeter.cloud')
url = base.rstrip('/') + '/api/v1/events'
headers = {'Authorization': f"Bearer {os.environ['OPENMETER_API_KEY']}", 'Content-Type': 'application/cloudevents+json'}
event = {'specversion': '1.0', 'type': 'litellm_tokens', 'id': 'preflight', 'time': datetime.datetime.now(datetime.timezone.utc).isoformat(), 'subject': 'preflight', 'source': 'litellm-proxy', 'data': {'model': 'test'}}
r = httpx.post(url, headers=headers, json=event, timeout=10)
if r.status_code >= 400:
raise SystemExit(f'OpenMeter preflight failed: {r.status_code} {r.text[:200]}') Try / catch
try:
result = litellm.completion(...)
except Exception as e:
if 'OpenMeter logging error' in str(e):
# logging-side failure; the LLM result may still be recoverable from kwargs/response
# inspect embedded response text (auth vs endpoint) and fix config
log_warning('openmeter export failed', error=str(e))
else:
raise Prevention
- Preflight the OpenMeter endpoint/key with a direct HTTP call before enabling the callback in production
- Keep OPENMETER_API_ENDPOINT as the base URL — never include /api/v1/events
- Rotate keys through the same pipeline that updates the deployment env to avoid stale tokens
- Watch proxy logs for 'OpenMeter logging error' and alert on it — it indicates metering data loss
When it happens
Trigger: Any successful LLM call that then triggers the OpenMeter sync logging path while the OpenMeter API rejects the event: 401/403 from an invalid or rotated OPENMETER_API_KEY, 404 from a wrong OPENMETER_API_ENDPOINT (e.g. including /api/v1/events twice because the code already appends it, or a self-hosted base URL missing the right route), 4xx payload rejections, or 5xx from an OpenMeter outage.
Common situations: Expired/rotated OpenMeter tokens; base URL misconfiguration where the operator pasted the full events URL instead of the base (producing /api/v1/events/api/v1/events); self-hosted OpenMeter behind a gateway that returns HTML error pages (the HTML then appears inside the exception text); OpenMeter cloud incidents; proxy egress blocked by firewall returning a proxy 403.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- OpenMeter: user is required
- access_denied
- api_key and api_base are required for Arize Phoenix prompt…
- api_key is required
- API key is required
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/866cd10ad11ca382.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/integrations/openmeter.py:121
else:
_url += "/api/v1/events"
api_key: Final = os.getenv("OPENMETER_API_KEY")
_data: Final = self._common_logic(kwargs=kwargs, response_obj=response_obj)
_headers: Final = {
"Content-Type": "application/cloudevents+json",
"Authorization": f"Bearer {api_key}",
}
try:
self.sync_http_handler.post(
url=_url,
data=json.dumps(_data),
headers=_headers,
)
except httpx.HTTPStatusError as e:
raise Exception(f"OpenMeter logging error: {e.response.text}")
except Exception as e:
raise e
async def async_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"
else:
_url += "/api/v1/events"
api_key: Final = os.getenv("OPENMETER_API_KEY")
_data: Final = self._common_logic(kwargs=kwargs, response_obj=response_obj)
_headers: Final = {
"Content-Type": "application/cloudevents+json",
"Authorization": f"Bearer {api_key}",
}
View on GitHub (pinned to 77b7c6c40c)