moeru-ai/airi · error · Error

MiMo transcription failed: ${response.status} ${response.sta

Error message

MiMo transcription failed: ${response.status} ${response.statusText}${errorBody ? ` — ${errorBody}` : ''}

What it means

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.

Source

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

        const dataUri = await readBlobAsDataUri(file)
        const base64Data = dataUri.split(',')[1]
        const response = await fetch(new URL('chat/completions', baseUrl), {
          method: 'POST',
          headers: { 'Content-Type': 'application/json', 'api-key': apiKey },
          body: JSON.stringify({
            model: modelName,
            messages: [{
              role: 'user',
              content: [
                { type: 'text', text: 'Transcribe the audio content.' },
                { type: 'input_audio', input_audio: { data: base64Data, format: audioFormatFromDataUri(dataUri) } },
              ],
            }],
          }),
        })
        if (!response.ok) {
          const errorBody = await response.text().catch(() => '')
          throw new Error(`MiMo transcription failed: ${response.status} ${response.statusText}${errorBody ? ` — ${errorBody}` : ''}`)
        }

        const data = await response.json() as { choices?: Array<{ message?: { content?: string } }> }
        return new Response(JSON.stringify({ text: data.choices?.[0]?.message?.content || '' }), {
          status: 200,
          headers: { 'Content-Type': 'application/json' },
        })
      },
    }),
  }
}

export const providerMimoAudioSpeech = defineProvider<MimoSpeechConfig>({
  id: 'mimo-audio-speech',
  name: 'Xiaomi MiMo',
  nameLocalize: ({ t }) => t('settings.pages.providers.provider.mimo.title'),
  description: 'api.xiaomimimo.com',
  descriptionLocalize: ({ t }) => t('settings.pages.providers.provider.mimo.description'),

View on GitHub (pinned to 677329427f)

Solutions

  1. Read the `— errorBody` suffix in the message: MiMo usually states whether the problem is auth, payload, or model.
  2. Verify the `apiKey` field of the provider config and that the key is valid for api.xiaomimimo.com.
  3. Check `baseUrl` — it must be the API root (default `https://api.xiaomimimo.com/v1/`); the code joins `chat/completions` onto it.
  4. Confirm the audio data URI has a standard `audio/<format>` MIME the `audioFormatFromDataUri` helper recognizes and the base64 payload is intact.
  5. 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.

Example fix

// before
const text = await provider.transcribe(dataUri)
// after — surface the upstream reason and validate the payload first
if (!dataUri.startsWith('data:audio/'))
  throw new Error('MiMo transcription needs an audio/* data URI')
let text: string
try {
  text = await provider.transcribe(dataUri)
}
catch (error) {
  throw new Error(`MiMo transcription unavailable: ${errorMessageFrom(error)}`)
}
Defensive patterns

Strategy: try-catch

Validate before calling

function isAudioDataUri(value: string): boolean {
  return /^data:audio\/(wav|mp3|ogg|flac|m4a|webm);base64,[A-Za-z0-9+/]+=*$/.test(value)
}
if (!isAudioDataUri(dataUri))
  throw new Error('Provide a valid base64 audio data URI before transcribing')

Try / catch

try {
  const result = await provider.transcribe(dataUri)
}
catch (error) {
  const message = errorMessageFrom(error)
  if (message.includes('401'))
    // bad MiMo key — prompt for credentials
  else if (message.includes('413') || message.includes('400'))
    // payload too large or bad format — shrink/re-encode audio
  else
    throw error
}

Prevention

When it happens

Trigger: 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).

Common situations: 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`.

Related errors


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