BerriAI/litellm · error · ValueError
custom_llm_provider is required
Error message
custom_llm_provider is required
What it means
Thrown by SpeechToCompletionBridgeHandler.validate_input_kwargs when 'custom_llm_provider' is absent from kwargs or is not a str (handler.py:41). The bridge needs the resolved provider name (e.g. 'openai') to transform the TTS request into a chat/completions call. Because litellm's main_router normally injects custom_llm_provider, hitting this means the call bypassed standard routing or the provider could not be resolved.
Source
Thrown at litellm/endpoints/speech/speech_to_completion_bridge/handler.py:41
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")
if headers is None or not isinstance(headers, dict):
raise ValueError("headers is required")
headers = kwargs.get("headers")View on GitHub (pinned to 6c2dcb801b)
Solutions
- Use litellm.audio_speech()/litellm.speech() rather than invoking the bridge handler directly, so routing populates custom_llm_provider
- If direct invocation is required, pass custom_llm_provider="openai" explicitly
- Prefix the model with the provider (e.g. 'openai/gpt-4o-audio-preview') so the provider is resolvable
Example fix
# before
speech_to_completion_bridge_handler.speech(model="gpt-4o-audio-preview", input="hi", voice="alloy", optional_params={}, litellm_params={}, headers={}, logging_obj=logging_obj)
# after
speech_to_completion_bridge_handler.speech(model="gpt-4o-audio-preview", input="hi", voice="alloy", optional_params={}, litellm_params={}, headers={}, logging_obj=logging_obj, custom_llm_provider="openai") Defensive patterns
Strategy: validation
Validate before calling
provider = kwargs.get("custom_llm_provider")
if not isinstance(provider, str):
# let litellm routing resolve it instead of calling the handler directly
kwargs["model"] = f"openai/{model}" # explicit provider prefix
# or: kwargs["custom_llm_provider"] = "openai" Type guard
def has_resolved_provider(kwargs: dict) -> bool:
return isinstance(kwargs.get("custom_llm_provider"), str) Try / catch
try:
resp = litellm.audio_speech(model="openai/gpt-4o-audio-preview", input=text, voice=voice)
except ValueError as e:
if "custom_llm_provider is required" in str(e):
logger.error("Provider unresolved; prefix model with provider name")
raise Prevention
- Prefer litellm.audio_speech() over direct handler invocation so routing resolves the provider
- Prefix model names with an explicit provider ('openai/...', 'azure/...')
- Never strip custom_llm_provider from kwargs in middleware or mocks
When it happens
Trigger: Calling speech_to_completion_bridge_handler.speech(...) directly without custom_llm_provider; a model string formatted so get_llm_provider cannot resolve a provider (e.g. an unknown prefix) causing custom_llm_provider to be dropped; patched/mocked routing code that strips the key from kwargs.
Common situations: Custom integrations that call the bridge handler instead of litellm.audio_speech; model names without a recognizable provider prefix ('openai/...', 'azure/...'); unit tests with mocked router outputs.
Related errors
- litellm_params is required
- prompt_characters must be provided for tts calls. prompt_cha
- model is required
- input is required
- optional_params is required
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/b1623ea81261152f.
Report an issue: GitHub.