{"record":{"id":"866cd10ad11ca382","repo":"BerriAI/litellm","slug":"openmeter-logging-error-e-response-text","errorCode":null,"errorMessage":"OpenMeter logging error: {e.response.text}","messagePattern":"OpenMeter logging error: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/integrations/openmeter.py","lineNumber":121,"sourceCode":"        else:\n            _url += \"/api/v1/events\"\n\n        api_key: Final = os.getenv(\"OPENMETER_API_KEY\")\n\n        _data: Final = self._common_logic(kwargs=kwargs, response_obj=response_obj)\n        _headers: Final = {\n            \"Content-Type\": \"application/cloudevents+json\",\n            \"Authorization\": f\"Bearer {api_key}\",\n        }\n\n        try:\n            self.sync_http_handler.post(\n                url=_url,\n                data=json.dumps(_data),\n                headers=_headers,\n            )\n        except httpx.HTTPStatusError as e:\n            raise Exception(f\"OpenMeter logging error: {e.response.text}\")\n        except Exception as e:\n            raise e\n\n    async def async_log_success_event(self, kwargs, response_obj, start_time, end_time):\n        _url = os.getenv(\"OPENMETER_API_ENDPOINT\", \"https://openmeter.cloud\")\n        if _url.endswith(\"/\"):\n            _url += \"api/v1/events\"\n        else:\n            _url += \"/api/v1/events\"\n\n        api_key: Final = os.getenv(\"OPENMETER_API_KEY\")\n\n        _data: Final = self._common_logic(kwargs=kwargs, response_obj=response_obj)\n        _headers: Final = {\n            \"Content-Type\": \"application/cloudevents+json\",\n            \"Authorization\": f\"Bearer {api_key}\",\n        }\n","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/integrations/openmeter.py#L103-L139","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before (doubled path -> 404)\nOPENMETER_API_ENDPOINT=https://openmeter.cloud/api/v1/events\n# after (base URL only; code appends /api/v1/events)\nOPENMETER_API_ENDPOINT=https://openmeter.cloud","handlingStrategy":"try-catch","validationCode":"import os, httpx, json, datetime\n\nbase = os.getenv('OPENMETER_API_ENDPOINT', 'https://openmeter.cloud')\nurl = base.rstrip('/') + '/api/v1/events'\nheaders = {'Authorization': f\"Bearer {os.environ['OPENMETER_API_KEY']}\", 'Content-Type': 'application/cloudevents+json'}\nevent = {'specversion': '1.0', 'type': 'litellm_tokens', 'id': 'preflight', 'time': datetime.datetime.now(datetime.timezone.utc).isoformat(), 'subject': 'preflight', 'source': 'litellm-proxy', 'data': {'model': 'test'}}\nr = httpx.post(url, headers=headers, json=event, timeout=10)\nif r.status_code >= 400:\n    raise SystemExit(f'OpenMeter preflight failed: {r.status_code} {r.text[:200]}')","typeGuard":null,"tryCatchPattern":"try:\n    result = litellm.completion(...)\nexcept Exception as e:\n    if 'OpenMeter logging error' in str(e):\n        # logging-side failure; the LLM result may still be recoverable from kwargs/response\n        # inspect embedded response text (auth vs endpoint) and fix config\n        log_warning('openmeter export failed', error=str(e))\n    else:\n        raise","preventionTips":["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"],"tags":["openmeter","http-status-error","logging-callback","api-key","network"],"backgroundTag":"http-error-response","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}