moeru-ai/airi · error

Gemini TTS request failed: ${response.status} ${await respon

Error message

Gemini TTS request failed: ${response.status} ${await response.text().catch(() => '')}

What it means

The Gemini generateContent endpoint returned a non-OK HTTP status. The wrapper surfaces the status code plus the response body text (best effort) so the developer can see the API-side error reason such as invalid API key, quota, or invalid model name.

Source

Thrown at packages/provider-inference/src/providers/cloud/google-gemini-audio-speech/index.ts:99

    if (!body.model)
      throw new Error('Missing model for Gemini TTS')

    const response = await globalThis.fetch(new URL(`models/${body.model}:generateContent`, baseUrl), {
      method: 'POST',
      headers: { 'x-goog-api-key': apiKey, 'Content-Type': 'application/json' },
      body: JSON.stringify({
        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, 'google-gemini-audio-speech'>({
  id: 'google-gemini-audio-speech',
  name: 'Google Gemini',

View on GitHub (pinned to f679616c34)

Solutions

  1. Read the status and body text in the message to identify the API-side cause
  2. Verify the API key is valid and has the Gemini TTS API enabled
  3. Confirm the model id is a valid Gemini TTS model available to your account
  4. Retry with backoff on 429/5xx; fix the payload or key on 400/401/403
  5. Check quota and billing status in the Google AI console
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: ensure key and model present
if (!apiKey) throw new Error('Missing Gemini API key')
if (!model) throw new Error('Missing Gemini TTS model')

Try / catch

try {
  const audio = await speech({ input, model })
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Gemini TTS request failed:')) {
    const status = Number(e.message.match(/failed: (\d+)/)?.[1])
    if (status === 429 || status >= 500) await retryWithBackoff()
    else if (status === 401 || status === 403) fixApiKey()
    else if (status === 404) fixModelOrBaseUrl()
  }
}

Prevention

When it happens

Trigger: Any Gemini API rejection of the TTS request: invalid or missing x-goog-api-key, nonexistent/unsupported model, malformed request payload, quota exceeded, or transient 5xx from Google.

Common situations: Wrong or expired API key, using a model id not enabled for your project, exceeding free-tier limits, or regional unavailability of the preview TTS model.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of moeru-ai/airi@f679616c34 (2026-09-08). Data as JSON: /api/errors/036c265207dd33d9. Report an issue: GitHub.