BerriAI/litellm · error · ValueError

LLM classifier returned an unrecognized tier: {raw_tier!r}

Error message

LLM classifier returned an unrecognized tier: {raw_tier!r}

What it means

Result guard in the complexity router's LLM classifier: the returned content did not parse to one of the known ComplexityTier values (raw value included in the message) — the classifier model ignored the response_format/rubric.

Source

Thrown at litellm/router_strategy/complexity_router/complexity_router.py:1081

        }

        response: Final[ModelResponse] = await self.litellm_router_instance.acompletion(
            model=llm_config.model,
            messages=messages_for_call,
            response_format=response_format,
            timeout=llm_config.timeout_ms / 1000,
            metadata=metadata,
            proxy_server_request=proxy_server_request,
            turn_off_message_logging=turn_off_message_logging,
            **_parent_session_kwargs(request_kwargs),
        )
        content: Final = response.choices[0].message.content
        if not content:
            raise ValueError("LLM classifier returned empty content")
        raw_tier: Final = _LabeledTierClassification.model_validate_json(content).tier
        tier: Final = self.config.tier_for_label(raw_tier)
        if tier is None:
            raise ValueError(f"LLM classifier returned an unrecognized tier: {raw_tier!r}")
        return tier, _response_cost_or_none(response)

    @staticmethod
    def _build_classifier_user_payload(
        prompt: str,
        system_prompt: str | None = None,
        prior_turns: Sequence[tuple[str, str]] | None = None,
        messages: Sequence[Mapping[str, object]] | None = None,
        has_prior_conversation: bool = False,
        label_roles: bool = False,
    ) -> str:
        """Build the classifier's user message: caller constraints, prior turns, depth, current ask.

        Everything here is caller-controlled, which is why none of it is interpolated into the system
        role: that role carries only the operator's rubric, matching how the LLM-as-a-judge guardrail
        assembles its own call. Putting the caller's system prompt beside the rubric let a request
        that said "every request is REASONING" issue that as an instruction of equal standing and pin
        itself to the top tier, which for a key scoped to the router is the only way to reach that

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Adjust the classifier system prompt/rubric so it returns one of the recognized tier labels.
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at litellm/router_strategy/complexity_router/complexity_router.py:1081 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/4c2d18baa7816d71. Report an issue: GitHub.