BerriAI/litellm · error · ValueError

keyword_tier_rules entries must contain at least one non-emp

Error message

keyword_tier_rules entries must contain at least one non-empty keyword

What it means

Pydantic validator on KeywordTierRule: after stripping whitespace, the keywords list contains no non-empty keyword. An empty keyword would substring-match everything and hijack routing, so the rule is rejected.

Source

Thrown at litellm/router_strategy/complexity_router/config.py:71

    """A deterministic override: if any keyword matches, route to this tier."""

    keywords: list[str] = Field(
        min_length=1,
        description="Keywords/phrases that trigger this rule (lexical or semantic match)",
    )
    tier: ComplexityTier = Field(
        description="Tier to route to when this rule matches",
    )

    @model_validator(mode="after")
    def _normalize_keywords(self) -> "KeywordTierRule":
        # Strip and drop blank keywords. An empty/whitespace keyword is a routing foot-gun:
        # _keyword_matches treats "" / " " as a substring that matches essentially every
        # prompt, so a single stray blank would silently force this rule's tier for all
        # traffic. Require at least one real keyword to remain.
        cleaned: Final = [stripped for keyword in self.keywords if (stripped := keyword.strip())]
        if not cleaned:
            raise ValueError("keyword_tier_rules entries must contain at least one non-empty keyword")
        self.keywords = cleaned
        return self


class ReminderMarkerPair(BaseModel):
    """One open/close delimiter pair a harness wraps injected context in.

    Normalizing here rather than at the scan is what makes matching case-insensitive: markers reach
    the scan already lowered, so it lowercases only the haystack and never the needles. Stripping
    keeps YAML indentation whitespace from becoming part of the delimiter.
    """

    open: str = Field(description="Opening delimiter, e.g. '<system-reminder>'")
    close: str = Field(description="Closing delimiter, e.g. '</system-reminder>'")

    @model_validator(mode="after")
    def _normalize(self) -> "ReminderMarkerPair":
        open_marker: Final = self.open.strip().lower()

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Give each keyword_tier_rules entry at least one non-empty keyword.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at litellm/router_strategy/complexity_router/config.py:71 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/94cb6da16abb5ac9. Report an issue: GitHub.