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

  1. 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
  2. Verify OPENMETER_API_KEY is valid and current (curl -H 'Authorization: Bearer <key>' <endpoint>/api/v1/events with a test CloudEvent)
  3. 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
  4. 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

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


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)