moeru-ai/airi · error · Error

MiMo voice clone requires a base64 audio sample in data URI

Error message

MiMo voice clone requires a base64 audio sample in data URI format.

What it means

When the request selects the mimo-v2.5-tts-voiceclone model, the provider requires a voice sample: it falls back from body.voice_sample to config.voiceSample (both trimmed) and throws if neither is present. The sample must be a base64 data URI of reference audio; the check runs client-side before the HTTP request is built.

Source

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

          input?: string
          model?: string
          response_format?: string
          style_prompt?: string
          voice_sample?: string
          voice?: string
        }
        const model = body.model || defaultModel
        const format = body.response_format || defaultFormat
        const stylePrompt = body.style_prompt?.trim() || config.stylePrompt?.trim() || ''
        const voiceSample = body.voice_sample?.trim() || config.voiceSample?.trim() || ''
        const userPrompt = model === 'mimo-v2.5-tts-voiceclone'
          ? stylePrompt
          : stylePrompt || 'Use a natural, clear speaking style.'

        const audio: Record<string, string> = { format }
        if (model === 'mimo-v2.5-tts-voiceclone') {
          if (!voiceSample)
            throw new Error('MiMo voice clone requires a base64 audio sample in data URI format.')
          audio.voice = voiceSample
        }
        else if (model === 'mimo-v2.5-tts') {
          audio.voice = body.voice || defaultVoice
        }

        if (model === 'mimo-v2.5-tts-voicedesign' && !stylePrompt)
          throw new Error('MiMo voice design requires a style prompt in the user message.')

        const response = await fetch(new URL('chat/completions', baseUrl), {
          method: 'POST',
          headers: { 'Content-Type': 'application/json', 'api-key': apiKey },
          body: JSON.stringify({
            model,
            messages: [
              { role: 'user', content: userPrompt },
              { role: 'assistant', content: body.input ?? '' },
            ],

View on GitHub (pinned to 677329427f)

Solutions

  1. Record or upload a reference clip and pass it as voice_sample (base64 data URI), or save it as the provider's voiceSample setting
  2. Switch to mimo-v2.5-tts if no sample is available and a named voice is acceptable
  3. Validate in the UI that the sample exists before allowing the voiceclone model
  4. Trim and sanity-check the data URI prefix before sending

Example fix

// before
speech({ model: 'mimo-v2.5-tts-voiceclone', input: text }) // no voice_sample → throw

// after
speech({ model: 'mimo-v2.5-tts-voiceclone', input: text, voice_sample: recordedDataUri })
Defensive patterns

Strategy: validation

Validate before calling

const isAudioDataUri = (v: string) => /^data:audio\/[a-z0-9.+-]+;base64,/.test(v.trim())
if (model === 'mimo-v2.5-tts-voiceclone' && !isAudioDataUri(voiceSample))
  promptForVoiceSample()

Type guard

function isAudioDataUri(value: string): boolean {
  return /^data:audio\/[a-z0-9.+-]+;base64,[A-Za-z0-9+/=]+$/.test(value.trim())
}

Try / catch

try {
  await synthesize(text, { model: 'mimo-v2.5-tts-voiceclone', voice_sample: sample })
}
catch (err) {
  if (err.message.includes('voice clone'))
    openVoiceRecorderStep()
}

Prevention

When it happens

Trigger: Voice-clone model selected but no sample was recorded or uploaded in the UI; the sample exists only in provider settings that were never saved; a whitespace-only sample string; a UI flow that passes only the named-voice `voice` field while the model is voiceclone.

Common situations: User skips the recording step; the sample upload silently failed; a different model was configured in settings but the request overrides the model to voiceclone without supplying the sample.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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