BerriAI/litellm · error · Exception
Error loading blocked words file {file_path}: {e}
Error message
Error loading blocked words file {file_path}: {e} What it means
Generic Exception wrapping any non-FileNotFoundError failure while loading the blocked-words file. The wrapped cause (after the colon) is the real problem: yaml.YAMLError for malformed YAML syntax, PermissionError for unreadable files, ValueError from ContentFilterAction(...) for an invalid action value (only BLOCK/MASK-style enum members are accepted), or AttributeError when keyword is not a string and .lower() fails.
Source
Thrown at litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py:812
if not isinstance(data, dict) or "blocked_words" not in data:
raise ValueError("Invalid format: file must contain 'blocked_words' key with list of words")
for word_data in data["blocked_words"]:
if not isinstance(word_data, dict) or "keyword" not in word_data or "action" not in word_data:
verbose_proxy_logger.warning("Skipping invalid word entry: %s", word_data)
continue
keyword = word_data["keyword"].lower()
action = ContentFilterAction(word_data["action"])
description = word_data.get("description")
self.blocked_words[keyword] = (action, description)
verbose_proxy_logger.info("Loaded %s blocked words from %s", len(data["blocked_words"]), file_path)
except FileNotFoundError:
raise FileNotFoundError(f"Blocked words file not found: {file_path}")
except Exception as e:
raise Exception(f"Error loading blocked words file {file_path}: {e}")
def _find_pattern_spans(self, text: str, pattern_entry: CompiledPatternEntry) -> list[tuple[int, int]]:
"""Return all match spans for a pattern, applying contextual rules if required."""
regex: Final[Pattern[str]] = pattern_entry["regex"]
keyword_regex: Final[Pattern[str] | None] = pattern_entry.get("keyword_regex")
allow_word_numbers: Final[bool] = pattern_entry.get("allow_word_numbers", False)
keyword_matches: Final = list(keyword_regex.finditer(text)) if keyword_regex is not None else None
if keyword_matches is not None and not keyword_matches:
return []
match_spans: Final[list[tuple[int, int]]] = []
for match in regex.finditer(text):
if keyword_matches is not None and not self._match_near_keyword(
match.start(), match.end(), keyword_matches, text
):View on GitHub (pinned to 77b7c6c40c)
Solutions
- Read the exception text after the colon — it names the exact underlying error class and message.
- Validate the YAML parses: python -c "import yaml; yaml.safe_load(open('blocked_words.yaml'))".
- Make every action exactly a valid ContentFilterAction value (e.g. 'BLOCK', 'MASK') and every keyword a quoted string.
- Check file permissions so the proxy's runtime user can read the file.
Example fix
# before
blocked_words:
- keyword: 42 # unquoted number -> .lower() fails
action: block # wrong value for the action enum
# after
blocked_words:
- keyword: "42"
action: BLOCK Defensive patterns
Strategy: validation
Validate before calling
# Dry-run the full load: schema, enum actions, string keywords, permissions
import yaml
from litellm.types.proxy.guardrails.litellm_content_filter import ContentFilterAction
def dry_run_blocked_words(path: str) -> None:
with open(path) as f: # raises PermissionError early
data = yaml.safe_load(f) # raises YAMLError early
assert isinstance(data, dict) and "blocked_words" in data
for w in data["blocked_words"]:
assert isinstance(w["keyword"], str), f"keyword must be a string: {w}"
ContentFilterAction(w["action"]) # raises ValueError for bad actions Type guard
def blocked_words_entry_ok(entry: object) -> bool:
"""Narrow one parsed entry to the loadable shape (string keyword + valid action)."""
if not isinstance(entry, dict):
return False
kw, act = entry.get("keyword"), entry.get("action")
return isinstance(kw, str) and bool(kw) and isinstance(act, str) and act in ("BLOCK", "MASK") Prevention
- Quote every keyword in YAML — unquoted numbers/booleans make .lower() fail downstream.
- Use exactly BLOCK / MASK for action values; lowercase variants are rejected by the enum.
- Validate the file with the dry-run above in CI and after every edit.
- Ensure the proxy runtime user can read the file (chmod/chown), especially when it's root-owned in a container.
When it happens
Trigger: The blocked-words file exists and parses to a dict with blocked_words, but something inside fails: YAML syntax error (tabs, bad indentation), an action like 'block'/'censor' that is not a valid enum value, keyword as a number/None, or restrictive file permissions.
Common situations: Tabs instead of spaces in hand-edited YAML; lowercase action values copied from docs of other tools; a keyword field containing a number (e.g. 42) instead of a quoted string; file owned by root while the proxy runs as a non-root user.
Related errors
- Invalid format: file must contain 'blocked_words' key with l
- Content Filter: guardrail_name is required
- pattern_name is required for prebuilt patterns
- pattern is required for regex patterns
- Unknown pattern_type: {pattern_config.pattern_type}
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/444a865cdd999973.
Report an issue: GitHub.