{"record":{"id":"b1623ea81261152f","repo":"BerriAI/litellm","slug":"custom-llm-provider-is-required-b1623e","errorCode":null,"errorMessage":"custom_llm_provider is required","messagePattern":"custom_llm_provider is required","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/endpoints/speech/speech_to_completion_bridge/handler.py","lineNumber":41,"sourceCode":"\n\nclass SpeechToCompletionBridgeHandler:\n    def __init__(self):\n        from .transformation import SpeechToCompletionBridgeTransformationHandler\n\n        super().__init__()\n        self.transformation_handler = SpeechToCompletionBridgeTransformationHandler()\n\n    def validate_input_kwargs(self, kwargs: dict) -> SpeechToCompletionBridgeHandlerInputKwargs:\n        from litellm import LiteLLMLoggingObj\n\n        model: Final = kwargs.get(\"model\")\n        if model is None or not isinstance(model, str):\n            raise ValueError(\"model is required\")\n\n        custom_llm_provider: Final = kwargs.get(\"custom_llm_provider\")\n        if custom_llm_provider is None or not isinstance(custom_llm_provider, str):\n            raise ValueError(\"custom_llm_provider is required\")\n\n        input: Final = kwargs.get(\"input\")\n        if input is None or not isinstance(input, str):\n            raise ValueError(\"input is required\")\n\n        optional_params: Final = kwargs.get(\"optional_params\")\n        if optional_params is None or not isinstance(optional_params, dict):\n            raise ValueError(\"optional_params is required\")\n\n        litellm_params: Final = kwargs.get(\"litellm_params\")\n        if litellm_params is None or not isinstance(litellm_params, dict):\n            raise ValueError(\"litellm_params is required\")\n\n        headers = kwargs.get(\"headers\")\n        if headers is None or not isinstance(headers, dict):\n            raise ValueError(\"headers is required\")\n\n        headers = kwargs.get(\"headers\")","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/endpoints/speech/speech_to_completion_bridge/handler.py#L23-L59","documentation":"validate_input_kwargs in the speech-to-completion bridge raises ValueError(\"custom_llm_provider is required\") when kwargs[\"custom_llm_provider\"] is missing, None, or not a str. The bridge needs the provider string to route the synthesized chat-completion call (it is forwarded as custom_llm_provider to litellm.completion). Only direct/internal invocations of the handler hit this — litellm.speech() always supplies it.","triggerScenarios":"Calling speech_to_completion_bridge_handler.speech(...) directly without custom_llm_provider, or passing None (e.g. when get_llm_provider() failed upstream and the caller forwarded the None).","commonSituations":"Custom wrappers around the bridge that never resolved a provider; test harnesses building kwargs by hand; copied example code that predates the provider argument.","solutions":["Resolve the provider first with litellm.get_llm_provider(model=model) and pass its result as custom_llm_provider.","Use litellm.speech(model=\"openai/gpt-4o-audio-preview\", ...) — the \"<provider>/<model>\" syntax lets litellm derive and pass custom_llm_provider itself.","Supply all required kwargs in one dict when calling the handler directly (see SpeechToCompletionBridgeHandlerInputKwargs)."],"exampleFix":"# before\nhandler.speech(model=\"gpt-4o-audio-preview\", input=\"hi\", voice=\"alloy\", optional_params={}, litellm_params={}, headers={}, logging_obj=log)  # ValueError: custom_llm_provider is required\n\n# after\n_, custom_llm_provider = litellm.get_llm_provider(model=\"gpt-4o-audio-preview\")\nhandler.speech(model=\"gpt-4o-audio-preview\", input=\"hi\", voice=\"alloy\", optional_params={}, litellm_params={}, headers={}, logging_obj=log, custom_llm_provider=custom_llm_provider)","handlingStrategy":"validation","validationCode":"import litellm\n\ndef resolve_provider_or_fail(model: str) -> str:\n    _, provider = litellm.get_llm_provider(model=model)\n    if not isinstance(provider, str) or not provider:\n        raise ValueError(f\"could not resolve custom_llm_provider for {model!r}\")\n    return provider","typeGuard":"def is_valid_provider_kwarg(value: object) -> bool:\n    return isinstance(value, str) and len(value.strip()) > 0","tryCatchPattern":null,"preventionTips":["Derive custom_llm_provider with litellm.get_llm_provider(model) instead of hardcoding or forwarding None.","Use the \"<provider>/<model>\" naming convention so provider resolution is deterministic.","Type wrapper signatures against the handler's TypedDict so missing fields fail static checks."],"tags":["speech","tts","validation","kwargs","internal-api"],"backgroundTag":"missing-required-argument","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}