BerriAI/litellm · error · GuardrailRaisedException

Ovalix guardrail error: {e}

Error message

Ovalix guardrail error: {e}

What it means

Runtime GuardrailRaisedException (litellm's canonical guardrail failure exception) from OvalixGuard._generate_post_guardrail_llm_texts: a checkpoint call made while post-processing LLM responses raised an unexpected Exception (network error, non-2xx, malformed JSON, timeout), which is wrapped with should_wrap_with_default_message=False so the underlying cause text is preserved in the message. Unlike the config errors, this is an Ovalix Tracker outage/communication problem mid-request.

Source

Thrown at litellm/proxy/guardrails/guardrail_hooks/ovalix/ovalix.py:251

            post_guardrail_texts: Final = await self._generate_post_guardrail_llm_texts(
                texts, tracker_actor_id, session_id, self._pre_checkpoint_id
            )
            return {**inputs, "texts": post_guardrail_texts}
        return inputs

    async def _generate_post_guardrail_llm_texts(
        self, texts: list[str], actor: str, session_id: str, checkpoint_id: str
    ) -> list[str]:
        """Generate post-guardrail LLM responses for the given LLM responses."""
        post_guardrail_texts: Final[list[str]] = []

        is_first_response = True
        for llm_response in reversed(texts):
            try:
                resp = await self._call_checkpoint(llm_response, checkpoint_id, actor, session_id)
            except Exception as e:
                verbose_proxy_logger.exception("Ovalix apply_guardrail checkpoint call failed: %s", e)
                raise GuardrailRaisedException(
                    guardrail_name=self.guardrail_name,
                    message=f"Ovalix guardrail error: {e}",
                    should_wrap_with_default_message=False,
                ) from e

            action_type = (resp.get("action_type") or "").lower()
            blocking_message = self._get_trackers_corrected_message(resp) or BLOCKED_BY_OVALIX_FALLBACK_MESSAGE
            if action_type == BLOCKED_ACTION_TYPE and is_first_response:
                self._block_current_message(blocking_message)
            elif action_type == BLOCKED_ACTION_TYPE:
                post_guardrail_texts.insert(0, blocking_message)
            else:
                corrected_text = self._get_trackers_corrected_message(resp) or llm_response
                post_guardrail_texts.insert(0, corrected_text)
            is_first_response = False
        return post_guardrail_texts

    def _block_current_message(self, blocking_message: str) -> None:

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Inspect the wrapped '{e}' text and the logged exception ('Ovalix apply_guardrail checkpoint call failed') to classify: connectivity vs auth vs payload
  2. Fix tracker reachability/credentials (tracker_api_base, tracker headers) and verify the application/checkpoint ids in the Ovalix console
  3. Retry the request once transient network blips are ruled in or out
  4. If tracker availability is spotty, decouple: run Ovalix in monitoring capacity or add circuit-breaking around guarded routes

Example fix

# before: single checkpoint call can abort the whole response
resp = await guard._call_checkpoint(text, checkpoint_id, actor, session_id)

# after: fail visibly but isolate per-call failures
try:
    resp = await guard._call_checkpoint(text, checkpoint_id, actor, session_id)
except Exception as e:
    log.error("ovalix checkpoint failed for session=%s: %s", session_id, e)
    raise GuardrailRaisedException(
        guardrail_name=guard.guardrail_name,
        message=f"Ovalix guardrail error: {e}",
        should_wrap_with_default_message=False,
    ) from e
Defensive patterns

Strategy: try-catch

Validate before calling

# Operator preflight: probe the Ovalix tracker before enabling the guardrail in blocking mode
import httpx

def ovalix_tracker_reachable(api_base: str, headers: dict) -> bool:
    try:
        httpx.get(api_base, headers=headers, timeout=5.0)
        return True
    except (httpx.ConnectError, httpx.ReadTimeout):
        return False

Try / catch

from litellm.exceptions import GuardrailRaisedException

try:
    result = await guard.apply_guardrail(inputs=texts, request_data=data, input_type="response")
except GuardrailRaisedException as e:
    if str(e).startswith("Ovalix guardrail error:"):
        # underlying cause preserved because should_wrap_with_default_message=False
        log.exception("ovalix tracker failure", exc_info=e.__cause__)
        if is_transient(e.__cause__):  # timeout / 5xx
            return await retry_once(guard, texts, data)
    raise

Prevention

When it happens

Trigger: Ovalix Tracker API base unreachable or timing out while post-call scanning responses; tracker returns 4xx/5xx (bad application_id/checkpoint pair, expired token); response body not valid JSON so parsing throws — any of these inside post-call handling of one or more LLM response texts

Common situations: Ovalix SaaS degradation or maintenance windows; on-prem tracker behind a flaky ingress; token used in tracker headers expiring mid-session; the reversed-order loop failing on the first response and aborting the whole completion

Related errors


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