BerriAI/litellm · error · ProxyException

tier_labels must be a JSON object of tier name to display na

Error message

tier_labels must be a JSON object of tier name to display name: {e}

What it means

Input guard in _labeled_tiers_from_query: the tier_labels query parameter could not be parsed/validated as a JSON object of tier name to display name via ComplexityRouterConfig. The validators reject blank, duplicated, or canonical-name-stealing labels so the editor cannot prefill a rubric no router would accept; surfaced as a 400.

Source

Thrown at litellm/proxy/management_endpoints/model_management_endpoints.py:2208

        )


def _labeled_tiers_from_query(tier_labels: str | None) -> tuple[tuple[ComplexityTier, str], ...] | None:
    """Resolve the tier_labels query param into the labeled tiers the rubric is built from.

    Validated through ComplexityRouterConfig so the editor prefills what the router would send: the
    same field validators that reject a blank, duplicated, or canonical-name-stealing label on the
    write path reject it here, rather than this returning a rubric no router could be configured to
    use. A malformed value is the caller's error, so it surfaces as a 400.

    None when unset, letting classification_system_prompt apply its own default names.
    """
    if not tier_labels:
        return None
    try:
        return ComplexityRouterConfig(tier_labels=json.loads(tier_labels)).labeled_tiers()
    except (JSONDecodeError, ValidationError) as e:
        raise ProxyException(
            message=f"tier_labels must be a JSON object of tier name to display name: {e}",
            type=ProxyErrorTypes.bad_request_error,
            code=status.HTTP_400_BAD_REQUEST,
            param="tier_labels",
        ) from e


@router.get(
    "/auto_router/classifier/default_prompt",
    description="Get the built-in system prompt used by an auto-router's LLM classifier",
    tags=["model management"],  # mutable-ok: fastapi's decorator signature types tags as a list
    dependencies=[Depends(user_api_key_auth)],  # mutable-ok: fastapi's decorator signature types dependencies as a list
)
async def get_auto_router_classifier_default_prompt(
    context_window_size: int = DEFAULT_CLASSIFIER_CONTEXT_WINDOW_SIZE,
    tier_labels: str | None = None,
    classification_rubric: ClassificationRubric | None = None,
) -> AutoRouterClassifierDefaultPromptResponse:

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Pass tier_labels as a JSON object mapping tier name to display name.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at litellm/proxy/management_endpoints/model_management_endpoints.py:2208 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/5aeadf9ff4410a34. Report an issue: GitHub.