{"record":{"id":"5fe010171c12cba8","repo":"BerriAI/litellm","slug":"content-blocked-category-name-conditional-match","errorCode":null,"errorMessage":"Content blocked: {category_name} conditional match '{matched_phrase}' detected (severity: {severity})","messagePattern":"Content blocked: (.+?) conditional match '(.+?)' detected \\(severity: (.+?)\\)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py","lineNumber":1228,"sourceCode":"        detections: list[ContentFilterDetection] | None,\n    ) -> None:\n        \"\"\"Handle conditional category match detection and action.\"\"\"\n        if detections is not None:\n            category_detection: Final[CategoryKeywordDetection] = {\n                \"type\": \"category_keyword\",\n                \"category\": category_name,\n                \"keyword\": matched_phrase,\n                \"severity\": severity,\n                \"action\": action.value,\n            }\n            detections.append(category_detection)\n\n        if action == ContentFilterAction.BLOCK:\n            error_msg: Final = (\n                f\"Content blocked: {category_name} conditional match '{matched_phrase}' detected (severity: {severity})\"\n            )\n            verbose_proxy_logger.warning(error_msg)\n            raise HTTPException(\n                status_code=400,\n                detail={\n                    \"error\": error_msg,\n                    \"category\": category_name,\n                    \"matched_phrase\": matched_phrase,\n                    \"severity\": severity,\n                },\n            )\n        elif action == ContentFilterAction.MASK:\n            verbose_proxy_logger.warning(\n                \"Conditional match '%s' from %s detected but MASK action not supported for conditional categories\",\n                matched_phrase,\n                category_name,\n            )\n\n    def _handle_category_keyword_match(\n        self,\n        keyword: str,","sourceCodeStart":1210,"sourceCodeEnd":1246,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py#L1210-L1246","documentation":"HTTPException(400) raised by _handle_conditional_match when a conditional category phrase matches and the effective action is BLOCK. Conditional categories only trigger on a phrase when a related category keyword was also detected in the text (e.g. 'card' matters only alongside a credit-card keyword), and the severity from the category config is embedded in the message. Note the source logs that MASK is not supported for conditional categories — the only outcomes are block or log-and-continue.","triggerScenarios":"A guarded request's text contains both the conditional category's keyword and its conditional phrase, the category file's action (or default_action) for that match is BLOCK, and the severity threshold is met.","commonSituations":"False positives where innocuous text accidentally combines a keyword and a phrase; strict severity thresholds in the shipped category templates; testing real user prompts against a newly enabled category.","solutions":["Inspect the 400 detail: category, matched_phrase, and severity tell you exactly which conditional rule fired.","Tune the category YAML: raise the severity threshold, remove/adjust the conditional phrase, or change that match's action so it no longer blocks.","Handle it client-side as a policy rejection — do not retry the same content.","Sanitize or rephrase the input to break the keyword+phrase combination."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from fastapi import HTTPException\n\ndef is_conditional_filter_block(exc: HTTPException) -> bool:\n    d = exc.detail if isinstance(exc.detail, dict) else {}\n    return (\n        exc.status_code == 400\n        and str(d.get(\"error\", \"\")).startswith(\"Content blocked:\")\n        and \"conditional match\" in str(d.get(\"error\", \"\"))\n    )\n\ntry:\n    resp = await client.chat.completions.create(**params)\nexcept HTTPException as e:\n    if is_conditional_filter_block(e):\n        raise PolicyRejectedError(\n            user_message=\"Request blocked by content policy\",\n            internal_detail=e.detail,  # category/matched_phrase/severity — log only\n        ) from e\n    raise","preventionTips":["Remember MASK is unsupported for conditional categories — only tune thresholds/phrases/actions to soften them.","Test representative traffic against enabled categories in staging; conditional rules surprise with keyword+phrase combos.","Raise severity_threshold in the guardrail config to skip low-severity conditional matches entirely.","Map the 400 to a non-retryable client error; the same input always blocks again."],"tags":["content-moderation","content-filter","http-400","guardrails"],"backgroundTag":"content-filter-blocked","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}