BerriAI/litellm · warning · Exception

Response from opik API status_code

Error message

Response from opik API status_code: {response.status_code}, text: {response.text}

What it means

OpikLogger._sync_send POSTs a batch of span data to the Opik API and calls response.raise_for_status(), then additionally requires the response to be exactly 204 No Content — any other 2xx code raises Exception('Response from opik API status_code: ..., text: ...'). The outer except immediately catches it and records it via verbose_logger.exception('OpikLogger failed to send batch'), so it never propagates to the caller: it is an observability/log-line error, and the LLM request itself is unaffected.

Solutions

  1. Enable verbose/DEBUG logging and read the full logged exception — it includes the status code and response text from Opik, which identifies auth vs routing vs backend-version issues
  2. Verify OPIK_URL_OVERRIDE points at the correct Opik deployment base URL and that OPIK_API_KEY/OPIK_WORKSPACE_ID are valid for it
  3. Align versions: upgrade litellm (or pin an Opik backend version known compatible) so the batch endpoint returns the expected 204
  4. If the response text shows auth errors, rotate/re-set the Opik credentials in the deployment env

Example fix

# before
OPIK_URL_OVERRIDE=https://opik.myco.com/wrong/path
# after
OPIK_URL_OVERRIDE=https://opik.myco.com
# plus: pip install -U litellm to match the Opik API contract
Defensive patterns

Strategy: validation

Validate before calling

import os, httpx

base = os.getenv('OPIK_URL_OVERRIDE', 'https://www.comet.com/opik/api').rstrip('/')
key = os.environ.get('OPIK_API_KEY')
if key:
    r = httpx.get(f'{base}/check-readiness', timeout=10)  # cheap liveness/auth probe
    if r.status_code >= 400:
        raise SystemExit(f'Opik endpoint unhealthy or misconfigured: {r.status_code}')

Try / catch

# The logger already swallows and logs this via verbose_logger.exception.
# Guard at the observability layer instead:
import logging
h = logging.getLogger('LiteLLM')
h.addHandler(AlertOnSubstringHandler(substring='OpikLogger failed to send batch'))

Prevention

When it happens

Trigger: A successful Opik HTTP response with an unexpected status — e.g. 200/201/202 returning a body where the client contract expects 204 — typically caused by an endpoint mismatch (OPIK_URL_OVERRIDE pointing at a different Opik version or an incompatible path), a gateway/proxy that rewrites responses, or non-2xx raise_for_status failures logged through the same handler. Visible in verbose logs after LLM calls when Opik tracing is enabled.

Common situations: Self-hosted Opik (Comet) whose version returns a JSON body with 200 on batch ingest; reverse proxies (nginx, service meshes) injecting responses; OPIK_URL_OVERRIDE typos hitting the wrong route; version drift between litellm's Opik client expectations and the deployed Opik backend; workspace/API-key misconfigurations that produce error bodies instead of 204.

Related errors


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

Appendix: source

Thrown at litellm/integrations/opik/opik.py:175

                    "OpikLogger added event to log_queue - Will flush in %s seconds...", self.flush_interval
                )

                if len(self.log_queue) >= self.batch_size:
                    verbose_logger.debug("OpikLogger - Flushing batch")
                    await self.flush_queue()
        except Exception as e:
            verbose_logger.exception("OpikLogger failed to log success event - %s\n%s", e, traceback.format_exc())

    def _sync_send(self, url: str, headers: dict[str, str], batch: dict[str, Any]) -> None:
        try:
            response: Final = self.sync_httpx_client.post(
                url=url,
                headers=headers,
                json=batch,
            )
            response.raise_for_status()
            if response.status_code != 204:
                raise Exception(f"Response from opik API status_code: {response.status_code}, text: {response.text}")
        except Exception as e:
            verbose_logger.exception("OpikLogger failed to send batch - %s\n%s", e, traceback.format_exc())

    def log_success_event(
        self,
        kwargs: dict[str, Any],
        response_obj: Any,
        start_time: datetime,
        end_time: datetime,
    ) -> None:
        try:
            if _should_skip_event(kwargs):
                return

            # Build payload using the payload builder
            trace_payload, span_payload = opik_payload_builder.build_opik_payload(
                kwargs=kwargs,
                response_obj=response_obj,

View on GitHub (pinned to 77b7c6c40c)