BerriAI/litellm · error · ValueError

custom_llm_provider is required

Error message

custom_llm_provider is required

What it means

validate_input_kwargs raises when the kwargs dict lacks 'custom_llm_provider' or it is not a str. The bridge handler needs the resolved provider name to route the transformed Responses API call. Like the other kwargs checks in this method, it fires only when the handler is invoked with an incomplete hand-built kwargs dict rather than through litellm.completion.

Source

Thrown at litellm/completion_extras/litellm_responses_transformation/handler.py:114

        hidden_params: Final = getattr(stream_iter, "_hidden_params", None)
        response: Final = self._coerce_response_object(response_obj, hidden_params)
        if not isinstance(response, ResponsesAPIResponse):
            raise ValueError("Stream completed response is invalid")
        return response

    def validate_input_kwargs(self, kwargs: dict) -> ResponsesToCompletionBridgeHandlerInputKwargs:
        from litellm import LiteLLMLoggingObj
        from litellm.types.utils import ModelResponse

        typed_kwargs: Final[dict[str, object]] = kwargs

        model: Final = typed_kwargs.get("model")
        if model is None or not isinstance(model, str):
            raise ValueError("model is required")

        custom_llm_provider: Final = typed_kwargs.get("custom_llm_provider")
        if custom_llm_provider is None or not isinstance(custom_llm_provider, str):
            raise ValueError("custom_llm_provider is required")

        messages: Final = typed_kwargs.get("messages")
        if messages is None or not isinstance(messages, list):
            raise ValueError("messages is required")

        optional_params: Final = typed_kwargs.get("optional_params")
        if optional_params is None or not isinstance(optional_params, dict):
            raise ValueError("optional_params is required")

        litellm_params: Final = typed_kwargs.get("litellm_params")
        if litellm_params is None or not isinstance(litellm_params, dict):
            raise ValueError("litellm_params is required")

        headers: Final = typed_kwargs.get("headers")
        if headers is None or not isinstance(headers, dict):
            raise ValueError("headers is required")

        model_response: Final = typed_kwargs.get("model_response")

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Use litellm.completion(model="provider/model", ...) so the provider is resolved and passed automatically
  2. If calling directly, set custom_llm_provider to the resolved provider string (e.g. "openai", "azure") in kwargs
  3. Verify you are not passing the kwargs from get_optional_params directly without provider resolution

Example fix

# before
kwargs = {"model": "gpt-4o", "messages": msgs}

# after
kwargs = {
    "model": "gpt-4o",
    "custom_llm_provider": "openai",
    "messages": msgs,
    # ...remaining required keys per handler.py:16
}
Defensive patterns

Strategy: validation

Validate before calling

def has_provider_kwarg(kwargs: dict) -> bool:
    return isinstance(kwargs.get("custom_llm_provider"), str) and bool(kwargs["custom_llm_provider"])

Type guard

def is_valid_bridge_kwargs(kwargs: dict) -> bool:
    return isinstance(kwargs.get("custom_llm_provider"), str)

Prevention

When it happens

Trigger: Direct invocation of ResponsesToCompletionBridgeHandler.validate_input_kwargs / async_completion with kwargs missing custom_llm_provider (e.g. only model and messages supplied).

Common situations: Custom routing layers that build the kwargs dict themselves; tests stubbing the completion pipeline; upgrading litellm where the internal kwargs contract changed.

Related errors


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