{"record":{"id":"7e3c6aff622756f9","repo":"BerriAI/litellm","slug":"each-rule-must-specify-at-least-a-tool-name-or-too","errorCode":null,"errorMessage":"Each rule must specify at least a tool_name or tool_type regex","messagePattern":"Each rule must specify at least a tool_name or tool_type regex","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/types/proxy/guardrails/guardrail_hooks/tool_permission.py","lineNumber":52,"sourceCode":"        if isinstance(value, str):\n            stripped: Final = value.strip()\n            if not stripped:\n                return None\n            return stripped\n        return value\n\n    @field_validator(\"decision\", mode=\"before\")\n    @classmethod\n    def normalize_decision(cls, v):\n        \"\"\"Normalize decision to lowercase to handle case-insensitive input.\"\"\"\n        if isinstance(v, str):\n            return v.lower()\n        return v\n\n    @model_validator(mode=\"after\")\n    def _ensure_target_present(self):\n        if self.tool_name is None and self.tool_type is None:\n            raise ValueError(\"Each rule must specify at least a tool_name or tool_type regex\")\n        return self\n\n\nclass ToolResult(BaseModel):\n    \"\"\"\n    Represents a tool_result block to be added to the response\n    \"\"\"\n\n    type: str = Field(default=\"tool_result\", description=\"Should be 'tool_result'\")\n    tool_use_id: str = Field(description=\"ID of the tool use this result corresponds to\")\n    content: str = Field(description=\"Result content\")\n    is_error: bool = Field(default=True, description=\"Whether this is an error result\")\n\n\nclass PermissionError(BaseModel):\n    \"\"\"\n    Error information for permission denial\n    \"\"\"","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/types/proxy/guardrails/guardrail_hooks/tool_permission.py#L34-L70","documentation":"Pydantic model_validator on a tool-permission rule: both tool_name and tool_type are None after normalization, so the rule matches no tool and is unenforceable. At least one targeting field must be set.","triggerScenarios":"Thrown at litellm/types/proxy/guardrails/guardrail_hooks/tool_permission.py:52 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Add a tool_name or tool_type regex to every tool-permission rule.","Delete rules that match nothing."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}