{"record":{"id":"dc5a3e64183e2a25","repo":"BerriAI/litellm","slug":"violation-message","errorCode":null,"errorMessage":"{violation_message}","messagePattern":"\\{violation_message\\}","errorType":"exception","errorClass":"ModifyResponseException","httpStatus":null,"severity":"error","filePath":"litellm/integrations/custom_guardrail.py","lineNumber":240,"sourceCode":"                the synthetic block response reports it instead of zeros. Leave None\n                for pre-call/during-call blocks (the LLM was never invoked).\n\n        Raises:\n            ModifyResponseException: Always raises this exception to short-circuit\n                                     the LLM call and return the violation message\n\n        Example:\n            if violation_detected and self.on_flagged_action == \"passthrough\":\n                message = self._format_violation_message(detection_info)\n                self.raise_passthrough_exception(\n                    violation_message=message,\n                    request_data=data,\n                    detection_info=detection_info\n                )\n        \"\"\"\n        model: Final = request_data.get(\"model\", \"unknown\")\n\n        raise ModifyResponseException(\n            message=violation_message,\n            model=model,\n            request_data=request_data,\n            guardrail_name=self.guardrail_name,\n            detection_info=detection_info,\n            original_response=original_response,\n        )\n\n    def raise_sensitive_data_route_exception(\n        self,\n        route_to_model: str,\n        request_data: dict[str, Any],\n        detection_info: dict[str, Any] | None = None,\n    ) -> None:\n        \"\"\"\n        Raise an exception to reroute the request to a different model.\n\n        Use this when sensitive data is detected and the guardrail is configured","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/integrations/custom_guardrail.py#L222-L258","documentation":"raise_modify_response_exception() is a helper on CustomGuardrail that subclasses call to reject a completed LLM response: it raises ModifyResponseException carrying the guardrail name, detection_info, request data, and the original response so the proxy can surface the rejection. The message is fully caller-supplied ({violation_message}), typically built by _format_violation_message to name what was detected.","triggerScenarios":"A custom guardrail's response hook detects a violation and calls raise_modify_response_exception(violation_message=..., request_data=..., detection_info=...) — the template in this entry is the parameter, not a literal; guardrail unit tests exercising the flagged path.","commonSituations":"Writing custom guardrails on top of CustomGuardrail; PII/secrets/PCI detectors flagging model output; migrating a guardrail from manual HTTPException raises to the typed helper.","solutions":["Treat this as intended control flow: the guardrail flagged the response — fix the prompt/data or tune the guardrail rules/thresholds","If you own the guardrail, prefer configuring on_flagged_action ('blocked'/'masked') so the framework handles the response instead of the raw exception escaping","Catch ModifyResponseException where you invoke litellm and map it to a 4xx with the detection metadata for clients"],"exampleFix":"# before\nclass MyGuardrail(CustomGuardrail):\n    async def async_moderation_hook(self, data, response):\n        if violation_detected:\n            raise HTTPException(400, 'blocked')  # untyped, loses detection_info\n\n# after\nclass MyGuardrail(CustomGuardrail):\n    async def async_moderation_hook(self, data, response):\n        if violation_detected:\n            self.raise_modify_response_exception(\n                violation_message=self._format_violation_message(detection_info),\n                request_data=data, detection_info=detection_info,\n                original_response=response)\n# caller: except ModifyResponseException as e: return JSONResponse(status_code=400, content={'error': str(e)})","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    resp = await litellm.acompletion(...)\nexcept ModifyResponseException as e:\n    # guardrail flagged the completed response\n    return JSONResponse(status_code=400, content={'error': str(e), 'guardrail': e.guardrail_name})","preventionTips":["Map guardrail rejections to typed 4xx responses at the client boundary instead of crashing","Tune guardrail rules to reduce false positives before enforcing block behavior","Log detection_info from the exception for audit trails"],"tags":["guardrail","moderation","modify-response","litellm"],"backgroundTag":"content-moderation-blocked","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}