BerriAI/litellm · error · ValueError

model is required

Error message

model is required

What it means

Thrown by SpeechToCompletionBridgeHandler.validate_input_kwargs when the internal kwargs dict has no 'model' key or its value is not a str. This handler bridges /audio/speech (TTS) calls to chat/completions models (e.g. gpt-4o-audio-preview), and validates the assembled kwargs in litellm/endpoints/speech/speech_to_completion_bridge/handler.py:37. It indicates the speech() entrypoint was called without a usable model string, which normally only happens when routing/internal plumbing passes an empty model through.

Source

Thrown at litellm/endpoints/speech/speech_to_completion_bridge/handler.py:37

    litellm_params: dict
    logging_obj: "LiteLLMLoggingObj"
    headers: dict
    custom_llm_provider: str


class SpeechToCompletionBridgeHandler:
    def __init__(self):
        from .transformation import SpeechToCompletionBridgeTransformationHandler

        super().__init__()
        self.transformation_handler = SpeechToCompletionBridgeTransformationHandler()

    def validate_input_kwargs(self, kwargs: dict) -> SpeechToCompletionBridgeHandlerInputKwargs:
        from litellm import LiteLLMLoggingObj

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

        custom_llm_provider: Final = 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")

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

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

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

        headers = kwargs.get("headers")

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Pass a valid non-empty model string (e.g. 'gpt-4o-audio-preview') to the speech/TTS call
  2. If calling the handler directly, include model= in the kwargs passed to speech_to_completion_bridge_handler.speech()
  3. On the LiteLLM proxy, verify the request body to /v1/audio/speech contains a string 'model' field before routing

Example fix

# before
resp = litellm.audio_speech(model=None, input="hello", voice="alloy")

# after
resp = litellm.audio_speech(model="gpt-4o-audio-preview", input="hello", voice="alloy")
Defensive patterns

Strategy: validation

Validate before calling

def validate_speech_call(model, input_text, **kwargs):
    if not isinstance(model, str) or not model.strip():
        raise ValueError("model must be a non-empty string")
    if not isinstance(input_text, str):
        raise ValueError("input must be a string")

validate_speech_call(model, text)

Type guard

def is_valid_speech_model(model: object) -> bool:
    return isinstance(model, str) and len(model.strip()) > 0

Try / catch

try:
    resp = litellm.audio_speech(model=model, input=text, voice=voice)
except ValueError as e:
    if "model is required" in str(e):
        logger.error("TTS call missing model; check request body")
        raise

Prevention

When it happens

Trigger: Calling litellm.speech()/audio_speech routed through the speech_to_completion_bridge with model=None, model missing from the request, or model set to a non-string (e.g. a dict or int). Also reachable if custom router code invokes speech_to_completion_bridge_handler.speech(...) directly without a model argument.

Common situations: Proxy config or router code that forwards a malformed body to the /v1/audio/speech endpoint; passing a deployment object instead of the model name string; programmatic calls that build kwargs dynamically and omit 'model'.

Related errors


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