{"record":{"id":"f6d0e112225a7141","repo":"BerriAI/litellm","slug":"ovalix-application-id-or-checkpoint-id-not-resolv","errorCode":null,"errorMessage":"Ovalix: application_id or checkpoint_id not resolved","messagePattern":"Ovalix: application_id or checkpoint_id not resolved","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/guardrails/guardrail_hooks/ovalix/ovalix.py","lineNumber":176,"sourceCode":"        return normalized_actor_id\n\n    def _get_session_id(self, data: dict) -> str:\n        \"\"\"Return a unique identifier for the chat/session (actor + date + application_id).\"\"\"\n        actor_hash: Final = self._get_tracker_actor_id(data)\n        today: Final = datetime.datetime.now(datetime.timezone.utc).strftime(\"%Y-%m-%d\")\n        return f\"{actor_hash}_{today}_{self._application_id}\"\n\n    async def _call_checkpoint(\n        self,\n        content: str,\n        checkpoint_id: str,\n        actor: str,\n        session_id: str,\n    ) -> dict[str, Any]:\n        \"\"\"Call the Ovalix Tracker checkpoint API and return the JSON response.\"\"\"\n        application_id: Final = self._application_id\n        if not application_id or not checkpoint_id:\n            raise ValueError(\"Ovalix: application_id or checkpoint_id not resolved\")\n\n        url: Final = f\"{self._tracker_api_base}/tracking/custom_application/checkpoint\"\n        headers: Final = dict(self._tracker_headers)\n        payload: Final = {\n            \"application_id\": application_id,\n            \"checkpoint_id\": checkpoint_id,\n            \"actor\": actor,\n            \"session_id\": session_id,\n            \"data_type\": \"TEXT\",\n            \"data\": {\"content\": content},\n        }\n        response: Final = await self._async_handler.post(url, headers=headers, json=payload)\n        response.raise_for_status()\n        return response.json()\n\n    @log_guardrail_information\n    async def apply_guardrail(\n        self,","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/guardrails/guardrail_hooks/ovalix/ovalix.py#L158-L194","documentation":"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.","triggerScenarios":"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","commonSituations":"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","solutions":["Do not mutate a constructed OvalixGuard — rebuild it from a corrected config so _validate_config runs again","Ensure every event hook you enable has its matching checkpoint id resolved at construction time","If invoking guard internals directly, assert application_id and the checkpoint id are non-empty before calling","Report as a library bug if it fires with an ordinary config.yaml-driven setup, since validation should have caught it earlier"],"exampleFix":"# before: mutating hooks after init bypasses validation\nguard = OnyxGuard(**params)\nguard.supported_event_hooks.append(GuardrailEventHooks.pre_call)\nawait guard.apply_guardrail(...)\n\n# after: provide ids up front, construct once\nlitellm_params = {\n  \"application_id\": \"app_123\",\n  \"pre_checkpoint_id\": \"chk_pre_456\",\n  \"post_checkpoint_id\": \"chk_post_789\",\n  \"mode\": \"pre_call\",\n}","handlingStrategy":"validation","validationCode":"# Before invoking any checkpoint path programmatically\ndef ovalix_ids_ready(guard) -> bool:\n    return bool(getattr(guard, \"_application_id\", None)) and bool(\n        getattr(guard, \"_pre_checkpoint_id\", None) or getattr(guard, \"_post_checkpoint_id\", None)\n    )\n\nif direct_invocation and not ovalix_ids_ready(guard):\n    raise RuntimeError(\"Ovalix guard not fully configured; rebuild from config\")","typeGuard":null,"tryCatchPattern":"try:\n    await guard.apply_guardrail(inputs=..., request_data=data, input_type=\"request\")\nexcept ValueError as e:\n    if \"application_id or checkpoint_id not resolved\" in str(e):\n        # invariant break: rebuild the guard from validated config instead of patching it\n        guard = build_ovalix_guard_from_config(cfg)\n    else:\n        raise","preventionTips":["Treat guardrail objects as immutable after construction; rebuild on config change so _validate_config re-runs","Never append supported_event_hooks post-init without re-running config validation","If you subclass OvalixGuard, keep the id attributes non-empty or override _validate_config consistently"],"tags":["ovalix","guardrails","internal-invariant","defensive-check"],"backgroundTag":"missing-required-config","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}