BerriAI/litellm · error · ValueError

No audio part found in the response

Error message

No audio part found in the response

What it means

Raised by SpeechToCompletionBridgeTransformationHandler.transform_response (transformation.py:108) when the ModelResponse's first choice has message.audio set to None. The bridge works by asking a chat model for audio output; if the provider returns text-only content (no audio part), there is nothing to decode into HttpxBinaryResponseContent and the call fails.

Source

Thrown at litellm/endpoints/speech/speech_to_completion_bridge/transformation.py:108

        )

        return wav_header + pcm_data

    def _is_gemini_tts_model(self, model: str) -> bool:
        """Check if the model is a Gemini TTS model that returns PCM16 data."""
        return "gemini" in model.lower() and ("tts" in model.lower() or "preview-tts" in model.lower())

    def transform_response(self, model_response: "ModelResponse") -> "HttpxBinaryResponseContent":
        import base64

        import httpx

        from litellm.types.llms.openai import HttpxBinaryResponseContent
        from litellm.types.utils import Choices

        audio_part: Final = cast(Choices, model_response.choices[0]).message.audio
        if audio_part is None:
            raise ValueError("No audio part found in the response")
        audio_content: Final = audio_part.data

        # Decode base64 to get binary content
        binary_data = base64.b64decode(audio_content)

        # Check if this is a Gemini TTS model that returns raw PCM16 data
        model: Final = getattr(model_response, "model", "")
        headers: Final = {}
        if self._is_gemini_tts_model(model):
            # Convert PCM16 to WAV format for proper audio file playback
            binary_data = self._convert_pcm16_to_wav(binary_data)
            headers["Content-Type"] = "audio/wav"
        else:
            headers["Content-Type"] = "audio/mpeg"

        # Create an httpx.Response object
        response: Final = httpx.Response(status_code=200, content=binary_data, headers=headers)
        return HttpxBinaryResponseContent(response)

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Use an audio-capable chat model such as 'gpt-4o-audio-preview' or a Gemini TTS model
  2. Verify the request includes the audio parameters the bridge sets (e.g. audio={'voice': ..., 'format': 'wav'}) and that custom optional_params do not override them
  3. Inspect the raw completion response (message.content) to see what the model actually returned — often a text refusal or answer indicating audio was not generated
  4. If you need plain TTS, call the provider's TTS API directly (e.g. openai TTS) instead of the chat-completion bridge

Example fix

# before
resp = litellm.audio_speech(model="gpt-4o", input="hello", voice="alloy")  # no audio output

# after
resp = litellm.audio_speech(model="gpt-4o-audio-preview", input="hello", voice="alloy")
Defensive patterns

Strategy: type-guard

Validate before calling

AUDIO_CHAT_MODELS = {"gpt-4o-audio-preview", "gpt-4o-mini-audio-preview"}

def supports_audio_output(model: str) -> bool:
    m = model.split("/")[-1].lower()
    return m in AUDIO_CHAT_MODELS or "tts" in m  # gemini tts models

if not supports_audio_output(model):
    raise ValueError(f"{model} cannot return audio; use gpt-4o-audio-preview or a Gemini TTS model")

Type guard

def response_has_audio(model_response) -> bool:
    try:
        return model_response.choices[0].message.audio is not None
    except (IndexError, AttributeError):
        return False

Try / catch

try:
    audio = litellm.audio_speech(model=model, input=text, voice=voice)
except ValueError as e:
    if "No audio part found" in str(e):
        # model returned text-only; retry with an audio-capable model
        audio = litellm.audio_speech(model="gpt-4o-audio-preview", input=text, voice=voice)

Prevention

When it happens

Trigger: Using a chat model that does not support audio output (e.g. plain gpt-4o instead of gpt-4o-audio-preview); omitting modalities/audio request parameters so the provider returns a text answer; the provider ignoring the audio request; an error/empty choice shape from the provider.

Common situations: Pointing the speech bridge at a non-audio-capable model; missing or stripped audio-related optional_params (e.g. audio voice/format) in the transformed request; provider-side changes where audio responses are gated behind specific parameters; model_response.choices being empty (this raises IndexError instead — a sibling failure).

Related errors


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