{"record":{"id":"bbf050b8028db98d","repo":"moeru-ai/airi","slug":"gemini-tts-request-failed-response-status-aw","errorCode":null,"errorMessage":"Gemini TTS request failed: ${response.status} ${await response.text().catch(() => '')}","messagePattern":"Gemini TTS request failed: (.+?) (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/libs/providers/providers/google-gemini-audio-speech/index.ts","lineNumber":99,"sourceCode":"    if (!body.model)\n      throw new Error('Missing model for Gemini TTS')\n\n    const response = await globalThis.fetch(new URL(`models/${body.model}:generateContent`, baseUrl), {\n      method: 'POST',\n      headers: { 'x-goog-api-key': apiKey, 'Content-Type': 'application/json' },\n      body: JSON.stringify({\n        contents: [{ parts: [{ text: body.input }] }],\n        generationConfig: {\n          responseModalities: ['AUDIO'],\n          speechConfig: {\n            voiceConfig: { prebuiltVoiceConfig: { voiceName: body.voice || 'Kore' } },\n          },\n          ...(body.temperature !== undefined ? { temperature: body.temperature } : {}),\n        },\n      }),\n    })\n    if (!response.ok)\n      throw new Error(`Gemini TTS request failed: ${response.status} ${await response.text().catch(() => '')}`)\n\n    const data = await response.json() as {\n      candidates?: Array<{ content?: { parts?: Array<{ inlineData?: { data?: string } }> } }>\n    }\n    const audio = data.candidates?.[0]?.content?.parts?.find(part => part.inlineData)?.inlineData?.data\n    if (!audio)\n      throw new Error('Gemini TTS response missing audio data')\n\n    return new Response(toWavFromPCM16(decodeBase64(audio), 24000), {\n      status: 200,\n      headers: { 'Content-Type': 'audio/wav' },\n    })\n  }\n}\n\nexport const providerGoogleGeminiAudioSpeech = defineProvider<GoogleGeminiSpeechConfig>({\n  id: 'google-gemini-audio-speech',\n  name: 'Google Gemini',","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/packages/stage-ui/src/libs/providers/providers/google-gemini-audio-speech/index.ts#L81-L117","documentation":"Thrown by the Gemini TTS fetch wrapper when the Gemini API responds with a non-2xx status. The message includes the HTTP status and the raw response body (best-effort, empty on read failure). This is the upstream Google API rejecting the request — most often auth/quota/model issues. It fires only after the input/model body checks passed.","triggerScenarios":"globalThis.fetch to models/${model}:generateContent returns non-ok. Typical Google API errors: 400 (malformed request or unsupported model for TTS), 401/403 (invalid/missing API key or no access to the model), 429 (quota exceeded), 404 (model name wrong/unavailable).","commonSituations":"Wrong API key or key without Gemini API access. Quota/rate limit hit. Model id typo or a model that does not support AUDIO generation. Regional restriction. Billing not enabled on the Google Cloud project.","solutions":["Read the status and body in the message: 401/403 → fix the API key and ensure Gemini API is enabled; 429 → wait and retry with backoff; 404 → correct the model id; 400 → check the request shape.","Confirm the API key in provider settings is valid and has access to the chosen TTS model.","Verify the model id supports audio output (responseModalities: AUDIO).","Enable billing / check quota in the Google Cloud console for sustained 429s."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// before fetch, sanity-check the api key and model name\nif (!apiKey) throw new Error('Gemini API key required')\nif (!body.model) throw new Error('Gemini model required')\n// network/quota errors are server-authoritative; catch at runtime","typeGuard":"null","tryCatchPattern":"try {\n  const res = await provider.speech(model).fetch(url, { body: JSON.stringify(body) })\n}\ncatch (err) {\n  if (err instanceof Error && err.message.startsWith('Gemini TTS request failed')) {\n    // parse status: 401/403 fix key; 429 back off; 404 fix model id; 400 fix request shape\n  }\n  else throw err\n}","preventionTips":["Store a valid Gemini API key with Gemini API access enabled.","Use a TTS-capable model id that supports AUDIO output.","Enable billing and monitor quota to avoid sustained 429s."],"tags":["network","gemini","tts","api-error","google-api"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}