BerriAI/litellm · error · ValueError

Ovalix: application_id or checkpoint_id not resolved

Error message

Ovalix: application_id or checkpoint_id not resolved

What it means

Runtime ValueError raised defensively at the top of OvalixGuard._call_checkpoint: it refuses to build the checkpoint request unless both self._application_id and the supplied checkpoint_id are truthy. Normally _validate_config prevents ever reaching this state at init, so hitting it means the guard class's invariants were broken after construction — e.g. event hooks appended post-init without re-validation, subclass mutation of the id fields, or a checkpoint id resolution path returning None/empty.

Source

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

        return normalized_actor_id

    def _get_session_id(self, data: dict) -> str:
        """Return a unique identifier for the chat/session (actor + date + application_id)."""
        actor_hash: Final = self._get_tracker_actor_id(data)
        today: Final = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d")
        return f"{actor_hash}_{today}_{self._application_id}"

    async def _call_checkpoint(
        self,
        content: str,
        checkpoint_id: str,
        actor: str,
        session_id: str,
    ) -> dict[str, Any]:
        """Call the Ovalix Tracker checkpoint API and return the JSON response."""
        application_id: Final = self._application_id
        if not application_id or not checkpoint_id:
            raise ValueError("Ovalix: application_id or checkpoint_id not resolved")

        url: Final = f"{self._tracker_api_base}/tracking/custom_application/checkpoint"
        headers: Final = dict(self._tracker_headers)
        payload: Final = {
            "application_id": application_id,
            "checkpoint_id": checkpoint_id,
            "actor": actor,
            "session_id": session_id,
            "data_type": "TEXT",
            "data": {"content": content},
        }
        response: Final = await self._async_handler.post(url, headers=headers, json=payload)
        response.raise_for_status()
        return response.json()

    @log_guardrail_information
    async def apply_guardrail(
        self,

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Do not mutate a constructed OvalixGuard — rebuild it from a corrected config so _validate_config runs again
  2. Ensure every event hook you enable has its matching checkpoint id resolved at construction time
  3. If invoking guard internals directly, assert application_id and the checkpoint id are non-empty before calling
  4. Report as a library bug if it fires with an ordinary config.yaml-driven setup, since validation should have caught it earlier

Example fix

# before: mutating hooks after init bypasses validation
guard = OnyxGuard(**params)
guard.supported_event_hooks.append(GuardrailEventHooks.pre_call)
await guard.apply_guardrail(...)

# after: provide ids up front, construct once
litellm_params = {
  "application_id": "app_123",
  "pre_checkpoint_id": "chk_pre_456",
  "post_checkpoint_id": "chk_post_789",
  "mode": "pre_call",
}
Defensive patterns

Strategy: validation

Validate before calling

# Before invoking any checkpoint path programmatically
def ovalix_ids_ready(guard) -> bool:
    return bool(getattr(guard, "_application_id", None)) and bool(
        getattr(guard, "_pre_checkpoint_id", None) or getattr(guard, "_post_checkpoint_id", None)
    )

if direct_invocation and not ovalix_ids_ready(guard):
    raise RuntimeError("Ovalix guard not fully configured; rebuild from config")

Try / catch

try:
    await guard.apply_guardrail(inputs=..., request_data=data, input_type="request")
except ValueError as e:
    if "application_id or checkpoint_id not resolved" in str(e):
        # invariant break: rebuild the guard from validated config instead of patching it
        guard = build_ovalix_guard_from_config(cfg)
    else:
        raise

Prevention

When it happens

Trigger: Code that mutates guardrail.supported_event_hooks or the Ovalix guard's private ids after init; a subclass overriding _call_checkpoint inputs; calling the guard's internals directly (not via hooks) with an unset checkpoint_id; config objects reused across proxy reloads where ids got cleared

Common situations: Custom orchestration wiring Ovalix programmatically instead of via config; hot-reload of guardrail definitions that partially resets state; defensive trip during development of guardrail plugins

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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