{"record":{"id":"648fb59272de8d43","repo":"moeru-ai/airi","slug":"mimo-transcription-failed-response-status-re","errorCode":null,"errorMessage":"MiMo transcription failed: ${response.status} ${response.statusText}${errorBody ? ` — ${errorBody}` : ''}","messagePattern":"MiMo transcription failed: (.+?) (.+?)(.+?)` : ''\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/libs/providers/providers/mimo-audio/index.ts","lineNumber":196,"sourceCode":"        const dataUri = await readBlobAsDataUri(file)\n        const base64Data = dataUri.split(',')[1]\n        const response = await fetch(new URL('chat/completions', baseUrl), {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json', 'api-key': apiKey },\n          body: JSON.stringify({\n            model: modelName,\n            messages: [{\n              role: 'user',\n              content: [\n                { type: 'text', text: 'Transcribe the audio content.' },\n                { type: 'input_audio', input_audio: { data: base64Data, format: audioFormatFromDataUri(dataUri) } },\n              ],\n            }],\n          }),\n        })\n        if (!response.ok) {\n          const errorBody = await response.text().catch(() => '')\n          throw new Error(`MiMo transcription failed: ${response.status} ${response.statusText}${errorBody ? ` — ${errorBody}` : ''}`)\n        }\n\n        const data = await response.json() as { choices?: Array<{ message?: { content?: string } }> }\n        return new Response(JSON.stringify({ text: data.choices?.[0]?.message?.content || '' }), {\n          status: 200,\n          headers: { 'Content-Type': 'application/json' },\n        })\n      },\n    }),\n  }\n}\n\nexport const providerMimoAudioSpeech = defineProvider<MimoSpeechConfig>({\n  id: 'mimo-audio-speech',\n  name: 'Xiaomi MiMo',\n  nameLocalize: ({ t }) => t('settings.pages.providers.provider.mimo.title'),\n  description: 'api.xiaomimimo.com',\n  descriptionLocalize: ({ t }) => t('settings.pages.providers.provider.mimo.description'),","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-ui/src/libs/providers/providers/mimo-audio/index.ts#L178-L214","documentation":"Thrown by the MiMo audio transcription provider when the POST to `<baseUrl>/chat/completions` (model `mimo-v2-omni`, audio sent as a base64 `input_audio` content part) returns a non-2xx status. The message embeds the HTTP status, statusText, and whatever error body the MiMo endpoint returned, so the real cause is almost always visible in the message tail. This is a plain HTTP-level failure of the upstream MiMo API, not a local parsing error.","triggerScenarios":"Calling `provider.transcribe()` on the MiMo provider and the endpoint answers 401/403 (missing or invalid `apiKey`, which is sent as an `api-key` header), 404 (wrong `baseUrl` path), 400 (audio data URI with an unsupported/undetectable format via `audioFormatFromDataUri`, or base64 payload too large), or 5xx (MiMo outage/rate limit).","commonSituations":"Wrong or expired MiMo API key in provider settings; `baseUrl` edited to a path that does not expose `chat/completions` (the code appends `chat/completions` to the normalized base); pasting a data URI whose MIME prefix is not a recognized audio format; very long recordings exceeding upstream request-size limits; renaming the model id away from `mimo-v2-omni`.","solutions":["Read the `— errorBody` suffix in the message: MiMo usually states whether the problem is auth, payload, or model.","Verify the `apiKey` field of the provider config and that the key is valid for api.xiaomimimo.com.","Check `baseUrl` — it must be the API root (default `https://api.xiaomimimo.com/v1/`); the code joins `chat/completions` onto it.","Confirm the audio data URI has a standard `audio/<format>` MIME the `audioFormatFromDataUri` helper recognizes and the base64 payload is intact.","If the status is 429/5xx, wait and retry; if 400 persists, test the same payload with a short WAV clip to rule out size/format limits."],"exampleFix":"// before\nconst text = await provider.transcribe(dataUri)\n// after — surface the upstream reason and validate the payload first\nif (!dataUri.startsWith('data:audio/'))\n  throw new Error('MiMo transcription needs an audio/* data URI')\nlet text: string\ntry {\n  text = await provider.transcribe(dataUri)\n}\ncatch (error) {\n  throw new Error(`MiMo transcription unavailable: ${errorMessageFrom(error)}`)\n}","handlingStrategy":"try-catch","validationCode":"function isAudioDataUri(value: string): boolean {\n  return /^data:audio\\/(wav|mp3|ogg|flac|m4a|webm);base64,[A-Za-z0-9+/]+=*$/.test(value)\n}\nif (!isAudioDataUri(dataUri))\n  throw new Error('Provide a valid base64 audio data URI before transcribing')","typeGuard":null,"tryCatchPattern":"try {\n  const result = await provider.transcribe(dataUri)\n}\ncatch (error) {\n  const message = errorMessageFrom(error)\n  if (message.includes('401'))\n    // bad MiMo key — prompt for credentials\n  else if (message.includes('413') || message.includes('400'))\n    // payload too large or bad format — shrink/re-encode audio\n  else\n    throw error\n}","preventionTips":["Keep the provider config validator (apiKey/baseUrl non-empty) green before enabling the provider.","Normalize and check the data URI MIME prefix client-side before upload.","Cap recording length so the base64 payload stays within upstream limits.","Log the full `— errorBody` tail once; it names the exact upstream cause."],"tags":["network","api","audio","transcription","mimo"],"backgroundTag":"upstream-api-error","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}