{"record":{"id":"0707fbf4c55f8193","repo":"BerriAI/litellm","slug":"content-blocked-category-name-category-keyword","errorCode":null,"errorMessage":"Content blocked: {category_name} category keyword '{keyword}' detected (severity: {severity})","messagePattern":"Content blocked: (.+?) category keyword '(.+?)' detected \\(severity: (.+?)\\)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py","lineNumber":1267,"sourceCode":"        action: ContentFilterAction,\n        text: str,\n        detections: list[ContentFilterDetection] | None,\n    ) -> str:\n        \"\"\"Handle category keyword 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\": keyword,\n                \"severity\": severity,\n                \"action\": action.value,\n            }\n            detections.append(category_detection)\n\n        if action == ContentFilterAction.BLOCK:\n            error_msg = f\"Content blocked: {category_name} category keyword '{keyword}' detected (severity: {severity})\"\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                    \"keyword\": keyword,\n                    \"severity\": severity,\n                },\n            )\n        elif action == ContentFilterAction.MASK:\n            keyword_pattern_for_masking: Final = self._keyword_to_regex_pattern(keyword)\n            text = re.sub(\n                keyword_pattern_for_masking,\n                self.keyword_redaction_tag,\n                text,\n                flags=re.IGNORECASE,\n            )\n            verbose_proxy_logger.info(\n                \"Masked category keyword '%s' from %s (severity: %s)\", keyword, category_name, severity","sourceCodeStart":1249,"sourceCodeEnd":1285,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py#L1249-L1285","documentation":"HTTPException(400) raised by _handle_category_keyword_match when a category keyword match resolves to action BLOCK. Category files define keywords with a default_action (or per-keyword action) and a severity; when a listed keyword appears in the text and the action is BLOCK, the whole request is rejected with category, keyword, and severity in the detail payload.","triggerScenarios":"A guarded request's text contains a keyword listed in an enabled category file (e.g. a weapons or self-harm category), and that match's action — explicit or the category's default_action — is BLOCK.","commonSituations":"Shipped policy templates enabling strict categories by default; benign traffic tripping overly broad keywords (substring-like matches); a security/compliance team tightening categories without a staging pass.","solutions":["Read the 400 detail (category, keyword, severity) to identify which category file and keyword blocked the request.","Edit the category YAML: remove the keyword, narrow it, or change its action/default_action away from BLOCK.","Rephrase the input to drop the keyword when the block is legitimate.","Handle the 400 gracefully in the client — it is deterministic for the same input, so retries will not help."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from fastapi import HTTPException\n\ndef is_category_keyword_block(exc: HTTPException) -> bool:\n    d = exc.detail if isinstance(exc.detail, dict) else {}\n    return (\n        exc.status_code == 400\n        and \"category keyword\" in str(d.get(\"error\", \"\"))\n    )\n\ntry:\n    resp = await client.chat.completions.create(**params)\nexcept HTTPException as e:\n    if is_category_keyword_block(e):\n        # d['category'], d['keyword'], d['severity'] identify the exact rule\n        raise PolicyRejectedError(\"Request blocked by content policy\") from e\n    raise","preventionTips":["Audit enabled category files: broad keywords block benign traffic — narrow or remove them.","Change a category's default_action or per-keyword action if BLOCK is too strict for your users.","Keep severity_threshold tuned so low-severity keywords log instead of block.","Never auto-retry a policy 400; surface a friendly message and audit the detail."],"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"}