{"record":{"id":"5728e3fa97df282c","repo":"BerriAI/litellm","slug":"custom-llm-provider-is-required-for-anthropic-mess","errorCode":null,"errorMessage":"custom_llm_provider is required for Anthropic messages, passed in model={model}, custom_llm_provider={custom_llm_provider}","messagePattern":"custom_llm_provider is required for Anthropic messages, passed in model=(.+?), custom_llm_provider=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/anthropic/experimental_pass_through/messages/handler.py","lineNumber":566,"sourceCode":"            api_key=api_key,\n            api_base=api_base,\n            client=client,\n            custom_llm_provider=custom_llm_provider,\n            **kwargs,\n        )\n        if _should_route_to_responses_api(custom_llm_provider):\n            return LiteLLMMessagesToResponsesAPIHandler.anthropic_messages_handler(**_shared_kwargs)\n\n        # The in-gateway context_management polyfill runs inside\n        # ``async_anthropic_messages_handler`` so it can ``await`` the\n        # summarization model for ``compact_20260112``. ``context_management``\n        # is passed through as a regular kwarg.\n        return LiteLLMMessagesToCompletionTransformationHandler.anthropic_messages_handler(\n            **_shared_kwargs,\n        )\n\n    if custom_llm_provider is None:\n        raise ValueError(\n            f\"custom_llm_provider is required for Anthropic messages, passed in model={model}, custom_llm_provider={custom_llm_provider}\"\n        )\n\n    local_vars.update(kwargs)\n    anthropic_messages_optional_request_params: Final = (\n        AnthropicMessagesRequestUtils.get_requested_anthropic_messages_optional_param(\n            params=local_vars,\n            model=model,\n            drop_params=litellm_params.get(\"drop_params\") is True,\n            custom_llm_provider=custom_llm_provider,\n        )\n    )\n    if is_reasoning_auto_summary_enabled():\n        thinking_param: Final = anthropic_messages_optional_request_params.get(\"thinking\")\n        if isinstance(thinking_param, dict) and thinking_param.get(\"type\") != \"disabled\":\n            anthropic_messages_optional_request_params[\"thinking\"] = {\n                **thinking_param,\n                \"display\": \"summarized\",","sourceCodeStart":548,"sourceCodeEnd":584,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/anthropic/experimental_pass_through/messages/handler.py#L548-L584","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Prefix the model with the provider: model='anthropic/claude-3-5-sonnet-20241022'.","Or pass custom_llm_provider='anthropic' explicitly to the handler call.","If running through the proxy, ensure the model is present in litellm.model_list / model_info so provider resolution succeeds."],"exampleFix":"# before\nresponse = litellm.anthropic_messages(model=\"claude-3-5-sonnet\", messages=..., max_tokens=100)\n\n# after\nresponse = litellm.anthropic_messages(model=\"anthropic/claude-3-5-sonnet-20241022\", messages=..., max_tokens=100)","handlingStrategy":"validation","validationCode":"def resolve_model_spec(model: str, custom_llm_provider: str | None) -> tuple[str, str]:\n    if custom_llm_provider:\n        return model, custom_llm_provider\n    if \"/\" in model:\n        return model.split(\"/\", 1)[1], model.split(\"/\", 1)[0]\n    raise ValueError(f\"model {model!r} needs a provider prefix (e.g. 'anthropic/...') or custom_llm_provider\")","typeGuard":"def model_has_resolvable_provider(model: str, custom_llm_provider: str | None = None) -> bool:\n    return bool(custom_llm_provider) or (isinstance(model, str) and \"/\" in model)","tryCatchPattern":"try:\n    resp = litellm.anthropic_messages(model=model, ...)\nexcept ValueError as e:\n    if \"custom_llm_provider is required\" in str(e):\n        resp = litellm.anthropic_messages(model=f\"anthropic/{model}\", ...)\n    else:\n        raise","preventionTips":["Always use the 'provider/model' form for direct SDK calls outside the proxy.","When wrapping the API, default custom_llm_provider based on your deployment.","Register custom models in proxy model_list so provider inference succeeds."],"tags":["anthropic","routing","custom-llm-provider","configuration"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}