BerriAI/litellm · error · BaseLLMException

{error_message}

Error message

{error_message}

What it means

The generic error constructor of BaseTextToSpeechConfig: when a TTS request fails at the HTTP layer (non-2xx), litellm calls get_error_class(), which raises BaseLLMException carrying the provider's message ('{error_message}' in the traceback is that verbatim text), the status code, and headers. Callers usually see it mapped to a litellm.*StatusError or the raw BaseLLMException.

Source

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

                - body: The request body (JSON dict, XML string, or binary data)
                - headers: Provider-specific headers to merge with base headers
        """

    @abstractmethod
    def transform_text_to_speech_response(
        self,
        model: str,
        raw_response: httpx.Response,
        logging_obj: LiteLLMLoggingObj,
    ) -> "HttpxBinaryResponseContent":
        """
        Transform provider response to standard format
        """

    def get_error_class(self, error_message: str, status_code: int, headers: dict) -> BaseLLMException:
        from ..chat.transformation import BaseLLMException

        raise BaseLLMException(
            status_code=status_code,
            message=error_message,
            headers=headers,
        )

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Inspect status_code and the provider message on the exception; the root cause is almost always the upstream request (auth, voice, format, endpoint path).
  2. Validate voice/format against the provider's supported list before calling.
  3. For self-hosted backends, confirm the api_base path matches the OpenAI /audio/speech schema.
  4. Handle 429 with retries/backoff via litellm's num_retries or router fallbacks.

Example fix

# before
resp = litellm.text_to_speech(model="openai/tts-1", voice="sarah", input="hi")  # unknown voice

# after
resp = litellm.text_to_speech(model="openai/tts-1", voice="alloy", input="hi")  # supported voice

try:
    resp = litellm.text_to_speech(model="openai/tts-1", voice="alloy", input="hi")
except Exception as e:
    status = getattr(e, "status_code", None)
    if status == 400:
        logger.warning("bad TTS request: %s", e)
Defensive patterns

Strategy: try-catch

Validate before calling

SUPPORTED_VOICES = {"alloy", "echo", "fable", "onyx", "nova", "shimmer"}
assert voice in SUPPORTED_VOICES, f"unsupported voice {voice}"

Type guard

def is_tts_provider_error(e: BaseException) -> bool:
    return getattr(e, "__class__", None).__name__ == "BaseLLMException" and hasattr(e, "status_code")

Try / catch

try:
    speech = litellm.text_to_speech(model="openai/tts-1", voice=voice, input=text)
except BaseLLMException as e:
    if e.status_code == 400:
        voice = "alloy"  # fall back to a universally supported voice
        speech = litellm.text_to_speech(model="openai/tts-1", voice=voice, input=text)
    else:
        raise

Prevention

When it happens

Trigger: litellm.text_to_speech() hitting provider errors: 401 bad key, 400 unsupported voice/format combination, 429 quota, 5xx provider outage — the transformation layer converts the failed response into BaseLLMException.

Common situations: Wrong voice name for the model; requesting an unsupported response_format (e.g. mp3 vs wav/opus on some backends); expired keys; self-hosted TTS server returning 404 because the route doesn't match the OpenAI schema.

Related errors


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