BerriAI/litellm · error · ValueError

api_base is required

Error message

api_base is required

What it means

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.

Source

Thrown at litellm/llms/base_llm/text_to_speech/transformation.py:103

        api_base: str | None = None,
    ) -> dict:
        """
        Validate environment and return headers
        """
        return {}

    @abstractmethod
    def get_complete_url(
        self,
        model: str,
        api_base: str | None,
        litellm_params: dict,
    ) -> str:
        """
        Get the complete url for the request
        """
        if api_base is None:
            raise ValueError("api_base is required")
        return api_base

    @abstractmethod
    def transform_text_to_speech_request(
        self,
        model: str,
        input: str,
        voice: str | None,
        optional_params: dict,
        litellm_params: dict,
        headers: dict,
    ) -> TextToSpeechRequestData:
        """
        Transform request to provider-specific format.

        Returns:
            TextToSpeechRequestData: A structured dict containing:
                - body: The request body (JSON dict, XML string, or binary data)

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Pass api_base explicitly: litellm.text_to_speech(model='...', input='...', api_base='http://localhost:8880/v1').
  2. Set the matching environment variable (e.g. OPENAI_API_BASE / <PROVIDER>_API_BASE) in the runtime environment.
  3. For a custom provider config, give get_complete_url a sensible default endpoint instead of relying on the caller.

Example fix

# before
litellm.text_to_speech(model="openai/tts-1", input="hello")  # ValueError if no default base

# after
speech = litellm.text_to_speech(
    model="openai/tts-1", input="hello",
    api_base="http://localhost:8880/v1", api_key=os.environ["LOCAL_TTS_KEY"],
)
Defensive patterns

Strategy: validation

Validate before calling

api_base = kwargs.get("api_base") or os.getenv("OPENAI_API_BASE")
if api_base is None:
    raise ValueError("text_to_speech requires api_base (param or OPENAI_API_BASE)")

Try / catch

try:
    speech = litellm.text_to_speech(model=m, input=t, api_base=base)
except ValueError as e:
    if "api_base is required" in str(e):
        speech = litellm.text_to_speech(model=m, input=t, api_base=os.environ["TTS_BASE"])
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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