{"record":{"id":"3d5188ed3e608017","repo":"moeru-ai/airi","slug":"mimo-tts-response-missing-audio-data","errorCode":null,"errorMessage":"MiMo TTS response missing audio data","messagePattern":"MiMo TTS response missing audio data","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/libs/providers/providers/mimo-audio/index.ts","lineNumber":118,"sourceCode":"          headers: { 'Content-Type': 'application/json', 'api-key': apiKey },\n          body: JSON.stringify({\n            model,\n            messages: [\n              { role: 'user', content: userPrompt },\n              { role: 'assistant', content: body.input ?? '' },\n            ],\n            audio,\n          }),\n        })\n        if (!response.ok || !response.body)\n          throw new Error(`MiMo TTS request failed: ${response.status} ${response.statusText}`)\n\n        const data = await response.json() as {\n          choices?: Array<{ message?: { audio?: { data?: string } } }>\n        }\n        const audioBase64 = data.choices?.[0]?.message?.audio?.data\n        if (!audioBase64)\n          throw new Error('MiMo TTS response missing audio data')\n\n        const binary = atob(audioBase64)\n        const bytes = new Uint8Array(binary.length)\n        for (let index = 0; index < binary.length; index++)\n          bytes[index] = binary.charCodeAt(index)\n\n        let contentType = `audio/${format}`\n        if (format === 'wav')\n          contentType = 'audio/wav'\n        else if (format === 'mp3')\n          contentType = 'audio/mpeg'\n\n        return new Response(bytes.buffer, {\n          status: 200,\n          headers: { 'Content-Type': contentType },\n        })\n      },\n    }),","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-ui/src/libs/providers/providers/mimo-audio/index.ts#L100-L136","documentation":"The MiMo chat/completions call returned HTTP OK, but choices[0].message.audio.data is absent, so the provider refuses rather than running atob on nothing. A 200 without audio means the model answered in text or the gateway stripped the audio field — typically a model id that is not an audio-output variant or content that skipped synthesis.","triggerScenarios":"Model id routed to a text-only mimo variant; a gateway version returning audio under a different response shape; content policy producing a textual refusal; the audio field not applied because the model ignored it.","commonSituations":"Deployment updated and renamed tts models; request built with a chat model id by mistake; an intermediate proxy normalizing the response and dropping the audio key.","solutions":["Confirm the model id is a tts variant (mimo-v2.5-tts, -voiceclone, -voicedesign)","Log the full choices[0].message to see whether text came back instead of audio","Check the gateway version and docs for the expected audio response shape","Retry with the plain tts model and a named voice to isolate the cause"],"exampleFix":"// before\nmodel: 'mimo-v2.5-chat' // text model → 200 with no audio → throw\n\n// after\nmodel: 'mimo-v2.5-tts' // audio-capable variant returns choices[0].message.audio.data","handlingStrategy":"try-catch","validationCode":"const TTS_MODELS = new Set(['mimo-v2.5-tts', 'mimo-v2.5-tts-voiceclone', 'mimo-v2.5-tts-voicedesign'])\nif (!TTS_MODELS.has(model))\n  throw new Error(`Model ${model} does not produce audio`)","typeGuard":null,"tryCatchPattern":"try {\n  const wav = await synthesize(text, { model })\n}\ncatch (err) {\n  if (err.message.includes('missing audio data'))\n    console.warn('MiMo returned text-only:', lastChoicesMessage)\n}","preventionTips":["Restrict the model picker to tts-capable ids","Log the raw choices payload when audio is absent","Pin gateway and model versions together in config"],"tags":["mimo","tts","empty-response","model-id"],"backgroundTag":"empty-api-response","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}