{"record":{"id":"dff78d71bf98161a","repo":"BerriAI/litellm","slug":"blocked-pii-entity","errorCode":"blocked_pii_entity","errorMessage":"Blocked entity detected: {entity_type} by Guardrail: {guardrail_name}. This entity is not allowed to be used in this request.","messagePattern":"Blocked entity detected: (.+?) by Guardrail: (.+?)\\. This entity is not allowed to be used in this request\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"litellm/proxy/_experimental/mcp_server/rest_endpoints.py","lineNumber":1056,"sourceCode":"            verbose_logger.info(\n                \"MCP tool call missing per-user env vars: server_id=%s missing=%s\",\n                e.server_id,\n                e.missing,\n            )\n            raise HTTPException(\n                status_code=412,\n                detail={\n                    \"error\": \"missing_user_env_vars\",\n                    \"message\": str(e),\n                    \"server_id\": e.server_id,\n                    \"server_name\": e.server_name,\n                    \"missing\": e.missing,\n                    \"setup_url\": e.setup_url,\n                },\n            )\n        except BlockedPiiEntityError as e:\n            verbose_logger.error(\"BlockedPiiEntityError in MCP tool call: %s\", e)\n            raise HTTPException(\n                status_code=400,\n                detail={\n                    \"error\": \"blocked_pii_entity\",\n                    \"message\": str(e),\n                    \"entity_type\": getattr(e, \"entity_type\", None),\n                    \"guardrail_name\": getattr(e, \"guardrail_name\", None),\n                },\n            )\n        except GuardrailRaisedException as e:\n            verbose_logger.error(\"GuardrailRaisedException in MCP tool call: %s\", e)\n            raise HTTPException(\n                status_code=400,\n                detail={\n                    \"error\": \"guardrail_violation\",\n                    \"message\": str(e),\n                    \"guardrail_name\": getattr(e, \"guardrail_name\", None),\n                },\n            )","sourceCodeStart":1038,"sourceCodeEnd":1074,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/_experimental/mcp_server/rest_endpoints.py#L1038-L1074","documentation":"LiteLLM guardrail hooks inspect MCP tool calls before dispatch. When a PII guardrail running in blocking mode detects an entity type configured as blocked (for example an email address or phone number) in the request, it raises BlockedPiiEntityError, which this handler maps to HTTP 400 with error code blocked_pii_entity, including entity_type and guardrail_name.","triggerScenarios":"A guardrail with PII blocking (e.g., Presidio masking_config with blocked_entity_types, or block mode) is attached to the proxy, and the tool-call arguments contain a matching entity such as EMAIL_ADDRESS or PHONE_NUMBER.","commonSituations":"Org-wide guardrails rolled out after agent workflows were already built; CRM or messaging MCP tools (send email, create lead) receiving raw user contact data.","solutions":["Remove or redact the blocked entity type from the tool arguments before sending.","Ask the proxy admin to switch the guardrail from block to mask/correction mode, or drop that entity_type from blocked_entity_types.","Route the workflow through a request tag whose guardrail set permits this data."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import re\n\n_PII_PATTERNS = {\n    \"EMAIL_ADDRESS\": re.compile(r\"[\\w.+-]+@[\\w-]+\\.[\\w.]+\"),\n    \"PHONE_NUMBER\": re.compile(r\"\\+?\\d[\\d\\s().-]{7,}\\d\"),\n}\n\ndef has_blocked_pii(text: str) -> list[str]:\n    return [name for name, rx in _PII_PATTERNS.items() if rx.search(text)]\n\nhits = has_blocked_pii(json.dumps(arguments))\nif hits:\n    redact_before_sending(hits)","typeGuard":"def is_blocked_pii_response(resp_json: dict) -> bool:\n    d = resp_json.get(\"detail\", {})\n    return isinstance(d, dict) and d.get(\"error\") == \"blocked_pii_entity\"","tryCatchPattern":"except httpx.HTTPStatusError as e:\n    d = e.response.json().get(\"detail\", {})\n    if e.response.status_code == 400 and isinstance(d, dict) and d.get(\"error\") == \"blocked_pii_entity\":\n        # entity_type and guardrail_name tell you exactly what tripped;\n        # redact and retry, or route the workflow elsewhere\n        log_pii_block(entity=d.get(\"entity_type\"), guardrail=d.get(\"guardrail_name\"))\n        return\n    raise","preventionTips":["Scan tool arguments for obvious PII (emails, phone numbers) before sending when a blocking guardrail is active.","Prefer masked-credential fields over raw user contact data in MCP tool payloads.","Ask the proxy admin which entity types are blocked so redaction targets the right data."],"tags":["guardrails","pii","mcp","http-400"],"backgroundTag":"guardrail-content-blocked","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}