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
- 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.
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
- 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.
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
- Streaming transcription request failed with status ${respons
- MiMo TTS request failed: ${response.status} ${response.statu
- MiniMax TTS request failed: ${response.status} ${response.st
- audio models upstream ${res.status}: ${await res.text().catc
- audio voices upstream ${res.status}: ${await res.text().catc
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/648fb59272de8d43.
Report an issue: GitHub.