BerriAI/litellm · error · ValueError

custom_llm_provider is required for Anthropic messages, pass

Error message

custom_llm_provider is required for Anthropic messages, passed in model={model}, custom_llm_provider={custom_llm_provider}

What it means

Raised in the Anthropic messages handler when the requested model can be routed by the litellm proxy (e.g. via model_list) but no custom_llm_provider could be resolved, and the model is not one of the known model-info paths that infer the provider. litellm needs custom_llm_provider to pick the correct provider transformation, so a None value after all resolution attempts is fatal.

Source

Thrown at litellm/llms/anthropic/experimental_pass_through/messages/handler.py:566

            api_key=api_key,
            api_base=api_base,
            client=client,
            custom_llm_provider=custom_llm_provider,
            **kwargs,
        )
        if _should_route_to_responses_api(custom_llm_provider):
            return LiteLLMMessagesToResponsesAPIHandler.anthropic_messages_handler(**_shared_kwargs)

        # The in-gateway context_management polyfill runs inside
        # ``async_anthropic_messages_handler`` so it can ``await`` the
        # summarization model for ``compact_20260112``. ``context_management``
        # is passed through as a regular kwarg.
        return LiteLLMMessagesToCompletionTransformationHandler.anthropic_messages_handler(
            **_shared_kwargs,
        )

    if custom_llm_provider is None:
        raise ValueError(
            f"custom_llm_provider is required for Anthropic messages, passed in model={model}, custom_llm_provider={custom_llm_provider}"
        )

    local_vars.update(kwargs)
    anthropic_messages_optional_request_params: Final = (
        AnthropicMessagesRequestUtils.get_requested_anthropic_messages_optional_param(
            params=local_vars,
            model=model,
            drop_params=litellm_params.get("drop_params") is True,
            custom_llm_provider=custom_llm_provider,
        )
    )
    if is_reasoning_auto_summary_enabled():
        thinking_param: Final = anthropic_messages_optional_request_params.get("thinking")
        if isinstance(thinking_param, dict) and thinking_param.get("type") != "disabled":
            anthropic_messages_optional_request_params["thinking"] = {
                **thinking_param,
                "display": "summarized",

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Prefix the model with the provider: model='anthropic/claude-3-5-sonnet-20241022'.
  2. Or pass custom_llm_provider='anthropic' explicitly to the handler call.
  3. If running through the proxy, ensure the model is present in litellm.model_list / model_info so provider resolution succeeds.

Example fix

# before
response = litellm.anthropic_messages(model="claude-3-5-sonnet", messages=..., max_tokens=100)

# after
response = litellm.anthropic_messages(model="anthropic/claude-3-5-sonnet-20241022", messages=..., max_tokens=100)
Defensive patterns

Strategy: validation

Validate before calling

def resolve_model_spec(model: str, custom_llm_provider: str | None) -> tuple[str, str]:
    if custom_llm_provider:
        return model, custom_llm_provider
    if "/" in model:
        return model.split("/", 1)[1], model.split("/", 1)[0]
    raise ValueError(f"model {model!r} needs a provider prefix (e.g. 'anthropic/...') or custom_llm_provider")

Type guard

def model_has_resolvable_provider(model: str, custom_llm_provider: str | None = None) -> bool:
    return bool(custom_llm_provider) or (isinstance(model, str) and "/" in model)

Try / catch

try:
    resp = litellm.anthropic_messages(model=model, ...)
except ValueError as e:
    if "custom_llm_provider is required" in str(e):
        resp = litellm.anthropic_messages(model=f"anthropic/{model}", ...)
    else:
        raise

Prevention

When it happens

Trigger: Calling anthropic_messages-style completion with model='claude-3-5-sonnet' (no 'anthropic/' prefix) outside a proxy deployment where model_info lookups succeed, and without passing custom_llm_provider='anthropic'. Also with custom model names that litellm cannot map to a provider.

Common situations: Using the SDK directly (not via the proxy) with a bare model name; custom_llm_provider passed as None explicitly by wrapper code; deployments where the model is not in the router's model_list so provider inference fails.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/5728e3fa97df282c. Report an issue: GitHub.