moeru-ai/airi · error
Missing model for Gemini TTS
Error message
Missing model for Gemini TTS
What it means
The wrapper validates that the parsed request body includes a model identifier before forwarding to models/{model}:generateContent. Without a model the URL would be malformed and the Gemini request would fail; the library throws locally with a clear message instead.
Solutions
- Explicitly pass the TTS model (e.g. 'gemini-2.5-flash-preview-tts') in the speech request
- Set a default model in the provider configuration so callers need not pass one each time
- Check stored settings/config for an empty model value and restore a valid one
- Confirm the option key for model matches what the provider expects
Example fix
// before
await speech({ input: 'hello', model: undefined })
// after
await speech({ input: 'hello', model: 'gemini-2.5-flash-preview-tts' }) Defensive patterns
Strategy: validation
Validate before calling
const GEMINI_TTS_MODELS = ['gemini-2.5-flash-preview-tts', 'gemini-2.5-pro-preview-tts']
if (!model || !GEMINI_TTS_MODELS.includes(model)) throw new Error(`Invalid or missing Gemini TTS model: ${model}`) Type guard
function hasModel(opts: { model?: string }): opts is { model: string } {
return typeof opts.model === 'string' && opts.model.length > 0
} Try / catch
try {
const audio = await speech({ input, model })
} catch (e) {
if (e instanceof Error && e.message.includes('Missing model')) {
// set a default model and retry
}
} Prevention
- Configure a default TTS model at the provider level so it is never undefined
- Validate model ids against a known list before calling
- Watch for settings migrations that may drop the stored model value
When it happens
Trigger: Calling the speech API without specifying the TTS model, or with a model value of empty string/undefined, so body.model is falsy after JSON.parse.
Common situations: Provider configured without a default model, a settings migration dropped the stored model, or the caller passed the model under a wrong option key.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- audio voices upstream returned malformed body
- Invalid request body
- Invalid request body
- Invalid request body
- Invalid request body
AI-assisted analysis of moeru-ai/airi@438a067dde (2026-09-08).
Data as JSON: /api/errors/f5a64b607336806d.
Report an issue: GitHub.
Appendix: source
Thrown at packages/provider-inference/src/providers/cloud/google-gemini-audio-speech/index.ts:82
bytes[index] = binary.charCodeAt(index)
return bytes
}
function createAudioFetch(apiKey: string, baseUrl: string) {
return async (_input: RequestInfo | URL, init?: RequestInit) => {
if (!init?.body || typeof init.body !== 'string')
throw new Error('Invalid request body')
const body = JSON.parse(init.body) as {
input?: string
model?: string
voice?: string
temperature?: number
}
if (!body.input)
throw new Error('Missing input text for Gemini TTS')
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(() => '')}`)
View on GitHub (pinned to 438a067dde)