moeru-ai/airi · error · Error
Gemini TTS response missing audio data
Error message
Gemini TTS response missing audio data
What it means
The Gemini call succeeded at the HTTP level, but candidates[0].content.parts contains no part with inlineData — the model produced no audio bytes — so the provider refuses rather than returning a broken WAV. A 200 without audio usually means the response was blocked or the model answered in text instead of generating speech.
Solutions
- Log the full response JSON — promptFeedback and finishReason explain the empty audio
- Adjust the prompt text that triggers safety blocks
- Confirm the model actually supports audio output with responseModalities AUDIO
- Retry with the default voice 'Kore' to rule out an invalid voiceName
Example fix
// before
const data = await response.json()
const audio = data.candidates?.[0]?.content?.parts?.find(p => p.inlineData)?.inlineData?.data
if (!audio) throw new Error('Gemini TTS response missing audio data') // opaque
// after
const data = await response.json()
const reason = data.promptFeedback?.blockReason ?? data.candidates?.[0]?.finishReason
if (!audio) throw new Error(`Gemini returned no audio: ${reason ?? 'unknown reason'}`) Defensive patterns
Strategy: fallback
Try / catch
try {
await speak(text)
}
catch (err) {
if (err.message.includes('missing audio data')) {
// Retry once with sanitized text and the default voice before giving up.
await speak(sanitize(text), { voice: 'Kore' })
}
} Prevention
- Inspect finishReason and promptFeedback whenever audio is absent
- Keep synthesis prompts short and neutral to avoid safety stops
- Validate the model supports AUDIO output before configuring it
When it happens
Trigger: Safety filters blocked the prompt (promptFeedback.blockReason or empty candidates); a finishReason like MAX_TOKENS or SAFETY cut generation; a model id that does not support the AUDIO response modality; an invalid voice name causing the API to return text only.
Common situations: Prompts with content the safety layer flags; the model swapped to a text-only variant while the voice config stayed; long input truncated before any audio part; regional model behavior differences.
Understand the failure class
Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.
Related errors
- Gemini TTS response missing audio data
- Gemini TTS request failed
- Gemini TTS request failed
- MiMo TTS response missing audio data
- MiMo TTS response missing audio data
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/0ebfacef3ca406ea.
Report an issue: GitHub.
Appendix: source
Thrown at packages/stage-ui/src/libs/providers/providers/google-gemini-audio-speech/index.ts:106
contents: [{ parts: [{ text: body.input }] }],
generationConfig: {
responseModalities: ['AUDIO'],
speechConfig: {
voiceConfig: { prebuiltVoiceConfig: { voiceName: body.voice || 'Kore' } },
},
...(body.temperature !== undefined ? { temperature: body.temperature } : {}),
},
}),
})
if (!response.ok)
throw new Error(`Gemini TTS request failed: ${response.status} ${await response.text().catch(() => '')}`)
const data = await response.json() as {
candidates?: Array<{ content?: { parts?: Array<{ inlineData?: { data?: string } }> } }>
}
const audio = data.candidates?.[0]?.content?.parts?.find(part => part.inlineData)?.inlineData?.data
if (!audio)
throw new Error('Gemini TTS response missing audio data')
return new Response(toWavFromPCM16(decodeBase64(audio), 24000), {
status: 200,
headers: { 'Content-Type': 'audio/wav' },
})
}
}
export const providerGoogleGeminiAudioSpeech = defineProvider<GoogleGeminiSpeechConfig>({
id: 'google-gemini-audio-speech',
name: 'Google Gemini',
nameLocalize: ({ t }) => t('settings.pages.providers.provider.google-gemini-audio-speech.title'),
description: 'aistudio.google.com',
descriptionLocalize: ({ t }) => t('settings.pages.providers.provider.google-gemini-audio-speech.description'),
tasks: ['text-to-speech', 'tts'],
icon: 'i-lobe-icons:gemini',
iconColor: 'i-lobe-icons:gemini-color',
createProviderConfig: () => googleGeminiSpeechConfigSchema,View on GitHub (pinned to 677329427f)