{"record":{"id":"b452a78bd274970f","repo":"BerriAI/litellm","slug":"api-base-is-required-b452a7","errorCode":null,"errorMessage":"api_base is required","messagePattern":"api_base is required","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/base_llm/text_to_speech/transformation.py","lineNumber":103,"sourceCode":"        api_base: str | None = None,\n    ) -> dict:\n        \"\"\"\n        Validate environment and return headers\n        \"\"\"\n        return {}\n\n    @abstractmethod\n    def get_complete_url(\n        self,\n        model: str,\n        api_base: str | None,\n        litellm_params: dict,\n    ) -> str:\n        \"\"\"\n        Get the complete url for the request\n        \"\"\"\n        if api_base is None:\n            raise ValueError(\"api_base is required\")\n        return api_base\n\n    @abstractmethod\n    def transform_text_to_speech_request(\n        self,\n        model: str,\n        input: str,\n        voice: str | None,\n        optional_params: dict,\n        litellm_params: dict,\n        headers: dict,\n    ) -> TextToSpeechRequestData:\n        \"\"\"\n        Transform request to provider-specific format.\n\n        Returns:\n            TextToSpeechRequestData: A structured dict containing:\n                - body: The request body (JSON dict, XML string, or binary data)","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/base_llm/text_to_speech/transformation.py#L85-L121","documentation":"BaseTextToSpeechConfig.get_complete_url() validates its input before returning: the text-to-speech default simply returns api_base, so a None api_base would silently produce an invalid URL (or crash later). It raises ValueError('api_base is required') when no base URL was resolved from litellm_params, provider defaults, or environment.","triggerScenarios":"Calling litellm.text_to_speech()/atext_to_speech() (or a provider TTS handler) where api_base resolves to None — custom provider without a default base and no api_base in the call or env.","commonSituations":"Self-hosted TTS (e.g. an OpenAI-compatible endpoint like Kokoro/Piper behind a gateway) without setting api_base or OPENAI_API_BASE; misnamed env var; deployments where the local .env isn't loaded.","solutions":["Pass api_base explicitly: litellm.text_to_speech(model='...', input='...', api_base='http://localhost:8880/v1').","Set the matching environment variable (e.g. OPENAI_API_BASE / <PROVIDER>_API_BASE) in the runtime environment.","For a custom provider config, give get_complete_url a sensible default endpoint instead of relying on the caller."],"exampleFix":"# before\nlitellm.text_to_speech(model=\"openai/tts-1\", input=\"hello\")  # ValueError if no default base\n\n# after\nspeech = litellm.text_to_speech(\n    model=\"openai/tts-1\", input=\"hello\",\n    api_base=\"http://localhost:8880/v1\", api_key=os.environ[\"LOCAL_TTS_KEY\"],\n)","handlingStrategy":"validation","validationCode":"api_base = kwargs.get(\"api_base\") or os.getenv(\"OPENAI_API_BASE\")\nif api_base is None:\n    raise ValueError(\"text_to_speech requires api_base (param or OPENAI_API_BASE)\")","typeGuard":null,"tryCatchPattern":"try:\n    speech = litellm.text_to_speech(model=m, input=t, api_base=base)\nexcept ValueError as e:\n    if \"api_base is required\" in str(e):\n        speech = litellm.text_to_speech(model=m, input=t, api_base=os.environ[\"TTS_BASE\"])\n    else:\n        raise","preventionTips":["For self-hosted TTS, always set the base URL explicitly in a shared client/config object.","Smoke-test TTS config in deployment health checks so missing env vars fail early."],"tags":["text-to-speech","configuration","api-base","value-error","litellm"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}