{"record":{"id":"aa11122940b099f9","repo":"BerriAI/litellm","slug":"content-blocked-pattern-name-pattern-detected","errorCode":null,"errorMessage":"Content blocked: {pattern_name} pattern detected","messagePattern":"Content blocked: (.+?) pattern detected","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py","lineNumber":1310,"sourceCode":"        pattern_name: str,\n        action: ContentFilterAction,\n        text: str,\n        spans: list[tuple[int, int]],\n        detections: list[ContentFilterDetection] | None,\n    ) -> str:\n        \"\"\"Handle regex pattern match detection and action.\"\"\"\n        if detections is not None:\n            pattern_detection: Final[PatternDetection] = {\n                \"type\": \"pattern\",\n                \"pattern_name\": pattern_name,\n                \"action\": action.value,\n            }\n            detections.append(pattern_detection)\n\n        if action == ContentFilterAction.BLOCK:\n            error_msg: Final = f\"Content blocked: {pattern_name} pattern detected\"\n            verbose_proxy_logger.warning(error_msg)\n            raise HTTPException(\n                status_code=400,\n                detail={\"error\": error_msg, \"pattern\": pattern_name},\n            )\n        elif action == ContentFilterAction.MASK:\n            redaction_tag: Final = self.pattern_redaction_format.format(pattern_name=pattern_name.upper())\n            text = self._mask_spans(text, spans, redaction_tag)\n            verbose_proxy_logger.info(\"Masked all %s matches in content\", pattern_name)\n\n        return text\n\n    def _handle_blocked_word_match(\n        self,\n        keyword: str,\n        action: ContentFilterAction,\n        description: str | None,\n        text: str,\n        detections: list[ContentFilterDetection] | None,\n    ) -> str:","sourceCodeStart":1292,"sourceCodeEnd":1328,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py#L1292-L1328","documentation":"HTTPException(400) raised by _handle_pattern_match when a compiled regex pattern (prebuilt catalog entries like SSN/credit card, or custom regex entries) matches the text with action BLOCK. The pattern_name in the message identifies which configured pattern fired; for MASK the handler would redact with pattern_redaction_format instead of raising.","triggerScenarios":"A guarded request's text matches a regex from litellm_params.patterns (or a pattern inherited from a policy template) whose action is BLOCK — e.g. a 9-digit SSN-like string triggering the 'ssn' prebuilt pattern.","commonSituations":"See trigger scenarios.","solutions":["Check the 400 detail's pattern field to see which pattern matched, and inspect the input for the offending content.","If the content is legitimate (e.g. test data, synthetic numbers), change that pattern's action from BLOCK to MASK so matches are redacted instead of rejected.","Tighten or replace an over-broad regex that produces false positives.","Handle the 400 client-side as a deterministic policy rejection — no retry."],"exampleFix":"# before — hard block on SSN-like content\npatterns:\n  - pattern_type: prebuilt\n    pattern_name: ssn\n    action: BLOCK\n\n# after — redact instead of block\npatterns:\n  - pattern_type: prebuilt\n    pattern_name: ssn\n    action: MASK","handlingStrategy":"try-catch","validationCode":"# Client-side pre-screen: run the same regexes before sending to the API\nimport re\n\nPATTERNS = {\"ssn\": re.compile(r\"\\d{3}-\\d{2}-\\d{4}\", re.IGNORECASE)}\n\ndef would_block(text: str, blocklist: set[str] = {\"ssn\"}) -> str | None:\n    for name in blocklist:\n        if PATTERNS[name].search(text):\n            return name\n    return None\n\n# if p := would_block(prompt): scrub or reject locally before the API call","typeGuard":"from fastapi import HTTPException\n\ndef is_pattern_block(exc: HTTPException) -> bool:\n    d = exc.detail if isinstance(exc.detail, dict) else {}\n    return exc.status_code == 400 and isinstance(d.get(\"pattern\"), str) and \"pattern detected\" in str(d.get(\"error\", \"\"))","tryCatchPattern":"try:\n    resp = await client.chat.completions.create(**params)\nexcept HTTPException as e:\n    if is_pattern_block(e):\n        pattern = e.detail[\"pattern\"]\n        raise PolicyRejectedError(\n            user_message=f\"Content matched the '{pattern}' filter and was blocked\",\n        ) from e\n    raise","preventionTips":["Prefer action: MASK for PII-style patterns (ssn, credit_card) — redact instead of rejecting the whole request.","Pre-screen inputs locally with the same regexes to fail fast with a better UX before the round-trip.","Review false-positive-prone regexes and tighten them; overly broad patterns block benign numbers.","Treat these 400s as deterministic: rephrase the input, don't retry."],"tags":["content-moderation","content-filter","regex","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"}