{"record":{"id":"cf202b9906c8e97a","repo":"moeru-ai/airi","slug":"minimax-tts-request-failed-response-status-r","errorCode":null,"errorMessage":"MiniMax TTS request failed: ${response.status} ${response.statusText}","messagePattern":"MiniMax TTS request failed: (.+?) (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/libs/providers/providers/minimax-speech/index.ts","lineNumber":61,"sourceCode":"              text: body.input ?? '',\n              stream: true,\n              voice_setting: {\n                voice_id: body.voice || 'English_Graceful_Lady',\n                speed: 1,\n                vol: 1,\n                pitch: 0,\n              },\n              audio_setting: {\n                sample_rate: 32000,\n                bitrate: 128000,\n                format: 'mp3',\n                channel: 1,\n              },\n            }),\n          })\n\n          if (!response.ok || !response.body)\n            throw new Error(`MiniMax TTS request failed: ${response.status} ${response.statusText}`)\n\n          // MiniMax streams SSE events that contain hex-encoded audio chunks.\n          const reader = response.body.getReader()\n          const decoder = new TextDecoder()\n          const audioChunks: Uint8Array[] = []\n          let buffer = ''\n\n          while (true) {\n            const { done, value } = await reader.read()\n            if (done)\n              break\n\n            buffer += decoder.decode(value, { stream: true })\n            const lines = buffer.split('\\n')\n            buffer = lines.pop() || ''\n            for (const line of lines) {\n              if (!line.startsWith('data:'))\n                continue","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-ui/src/libs/providers/providers/minimax-speech/index.ts#L43-L79","documentation":"Thrown by the MiniMax speech provider when the TTS request to the MiniMax API returns a non-OK status or a response without a body. At this point the HTTP call itself failed (auth, quota, invalid model/voice) — the SSE hex-audio-chunk parsing that follows never runs. Only `status` and `statusText` are reported; MiniMo-style error bodies are not included.","triggerScenarios":"POSTing the TTS payload (model, voice_id, audio_setting with sample_rate 32000 / mp3 / mono) and MiniMax answers 401 (invalid API key), 403 (unauthorized group), 400 (unknown voice_id or model name), 429 (rate/quota), or 5xx. Also triggered when a proxy strips the response body so `!response.body` holds even with status 200.","commonSituations":"API key or group id pasted incorrectly into provider settings; using a China-host (`api.minimax.chat`) key against the international host (`api.minimaxi.com`) or vice versa; voice id that belongs to a different model generation; account out of credits; corporate proxy buffering/removing the SSE body.","solutions":["Check `response.status` in the message: 401/403 → re-enter the MiniMax API key; 400 → verify model and voice_id; 429/5xx → quota or outage, retry later.","Confirm the base URL host matches the account region (minimax.chat vs minimaxi.com).","Verify the configured voice id exists for the configured model in the MiniMax console.","If status is 200 but body is missing, bypass or reconfigure the proxy so SSE streams pass through unbuffered."],"exampleFix":"// before\nif (!response.ok || !response.body)\n  throw new Error(`MiniMax TTS request failed: ${response.status} ${response.statusText}`)\n// after — include the upstream error body for diagnosis\nif (!response.ok || !response.body) {\n  const errorBody = !response.ok ? await response.text().catch(() => '') : ''\n  throw new Error(`MiniMax TTS request failed: ${response.status} ${response.statusText}${errorBody ? ` — ${errorBody}` : ''}`)\n}","handlingStrategy":"try-catch","validationCode":"if (!config.apiKey?.trim() || !config.groupId?.trim())\n  throw new Error('MiniMax credentials are incomplete — check provider settings')","typeGuard":null,"tryCatchPattern":"try {\n  const audio = await minimaxTts(payload)\n}\ncatch (error) {\n  const message = errorMessageFrom(error)\n  if (/401|403/.test(message))\n    // refresh MiniMix credentials\n  else if (/429|5\\d\\d/.test(message))\n    // transient — back off and retry once\n  else\n    throw error\n}","preventionTips":["Verify key + group id pair in the MiniMax console before configuring the provider.","Match the API host to the account region (minimax.chat vs minimaxi.com).","Use voice ids listed for the exact model configured.","Route SSE through proxies unbuffered."],"tags":["network","api","tts","minimax","speech"],"backgroundTag":"upstream-api-error","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}