moeru-ai/airi · error · Error

MiMo TTS request failed: ${response.status} ${response.statu

Error message

MiMo TTS request failed: ${response.status} ${response.statusText}

What it means

The POST to {baseUrl}/chat/completions for MiMo TTS returned a non-OK status or an empty body; the message embeds status and statusText (statusText can be empty on HTTP/2, leaving only the code). Authentication uses the api-key header, so key problems are the leading cause, followed by model and quota errors.

Source

Thrown at packages/stage-ui/src/libs/providers/providers/mimo-audio/index.ts:111

        }

        if (model === 'mimo-v2.5-tts-voicedesign' && !stylePrompt)
          throw new Error('MiMo voice design requires a style prompt in the user message.')

        const response = await fetch(new URL('chat/completions', baseUrl), {
          method: 'POST',
          headers: { 'Content-Type': 'application/json', 'api-key': apiKey },
          body: JSON.stringify({
            model,
            messages: [
              { role: 'user', content: userPrompt },
              { role: 'assistant', content: body.input ?? '' },
            ],
            audio,
          }),
        })
        if (!response.ok || !response.body)
          throw new Error(`MiMo TTS request failed: ${response.status} ${response.statusText}`)

        const data = await response.json() as {
          choices?: Array<{ message?: { audio?: { data?: string } } }>
        }
        const audioBase64 = data.choices?.[0]?.message?.audio?.data
        if (!audioBase64)
          throw new Error('MiMo TTS response missing audio data')

        const binary = atob(audioBase64)
        const bytes = new Uint8Array(binary.length)
        for (let index = 0; index < binary.length; index++)
          bytes[index] = binary.charCodeAt(index)

        let contentType = `audio/${format}`
        if (format === 'wav')
          contentType = 'audio/wav'
        else if (format === 'mp3')
          contentType = 'audio/mpeg'

View on GitHub (pinned to 677329427f)

Solutions

  1. Check the embedded status: 401/403 re-enter the API key; 429 back off; 404 fix baseUrl or model
  2. Confirm baseUrl reaches the MiMo gateway and appends chat/completions correctly
  3. Verify the model id is one of the mimo-v2.5-tts family
  4. Inspect the request in devtools — statusText alone may be empty

Example fix

// before
headers: { 'api-key': '' } // empty key reaches the server → 401

// after
if (!apiKey?.trim()) throw new Error('MiMo API key is required')
headers: { 'Content-Type': 'application/json', 'api-key': apiKey }
Defensive patterns

Strategy: try-catch

Validate before calling

if (!apiKey?.trim() || !URL.canParse(baseUrl))
  throw new Error('MiMo provider is not configured') // fail before the request

Try / catch

try {
  const audio = await mimoSpeech(body)
}
catch (err) {
  const [, status] = err.message.match(/MiMo TTS request failed: (\d+)/) ?? []
  if (status === '401' || status === '403') promptForApiKey()
  else if (status === '429') await backoffRetry()
}

Prevention

When it happens

Trigger: Missing or invalid api-key (401/403); a model id not served by this deployment (400/404); rate limit or quota (429); baseUrl pointing at a gateway route that does not proxy chat/completions (404/502).

Common situations: Key expired or revoked; environment config drifted between stages; a gateway in front of MiMo changed its routes; a deployment without audio-capable models.

Related errors


AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18). Data as JSON: /api/errors/0fab9d12417d6fbd. Report an issue: GitHub.