moeru-ai/airi · error · Error
Voice clone model requires a base64 audio sample in data URI
Error message
Voice clone model requires a base64 audio sample in data URI format.
What it means
Guard in the MiMo speech playground: selecting the `mimo-v2.5-tts-voiceclone` model switches the voice source from a catalogue voice id to a user-provided cloned-voice sample, which must be base64 audio embedded as a data URI (`voiceSample`). The code checks `!voiceSample.value.trim()` for exactly that model id and throws this validation error before calling `speechStore.speech`, so no network request is wasted on a request the backend would reject.
Source
Thrown at packages/stage-pages/src/pages/settings/providers/speech/mimo-audio-speech.vue:141
})
async function handleGenerateSpeech(input: string, voiceId: string, _useSSML: boolean, modelId?: string) {
const provider = await providersStore.getProviderInstance<SpeechProvider<string>>(providerId)
if (!provider) {
throw new Error('Failed to initialize speech provider')
}
const providerConfig = providerStore.getProviderConfig(providerId)
const modelToUse = modelId || model.value || defaultModel
const requestConfig = {
...providerConfig,
...defaultVoiceSettings,
stylePrompt: stylePrompt.value,
voiceSample: voiceSample.value,
}
if (modelToUse === 'mimo-v2.5-tts-voiceclone' && !voiceSample.value.trim()) {
throw new Error('Voice clone model requires a base64 audio sample in data URI format.')
}
const voiceToUse = modelToUse === 'mimo-v2.5-tts-voiceclone'
? voiceSample.value.trim()
: voiceId || (config.value?.voice || defaultVoice)
return await speechStore.speech(
provider,
modelToUse,
input,
voiceToUse,
requestConfig,
)
}
const {
isValidating,
isValid,View on GitHub (pinned to 677329427f)
Solutions
- Record or paste a base64 data-URI audio sample into the voice sample field before generating with the voiceclone model.
- Or switch the model selector back to a non-clone MiMo TTS model and pick a normal voice id.
- Ensure the sample is a full data URI (`data:audio/webm;base64,...` or similar), not bare base64, to avoid the next failure downstream.
- If cloning is unintended, clear the stored model so it falls back to the default non-clone model.
Example fix
// before
if (modelToUse === 'mimo-v2.5-tts-voiceclone' && !voiceSample.value.trim())
throw new Error('Voice clone model requires a base64 audio sample in data URI format.')
// after (surface it in the UI instead of only throwing at generate time)
const voiceCloneReady = computed(() => modelToUse.value !== 'mimo-v2.5-tts-voiceclone' || !!voiceSample.value.trim())
// template: <button :disabled="!voiceCloneReady">Generate</button>
if (modelToUse === 'mimo-v2.5-tts-voiceclone' && !voiceSample.value.trim())
throw new Error('Voice clone model requires a base64 audio sample in data URI format.') Defensive patterns
Strategy: validation
Validate before calling
const isVoiceCloneModel = (id: string) => id === 'mimo-v2.5-tts-voiceclone' const isDataUri = (s: string) => /^data:audio\/[a-z0-9.+-]+;base64,\S+$/i.test(s.trim()) const voiceCloneReady = computed(() => !isVoiceCloneModel(model.value) || isDataUri(voiceSample.value), ) // template: <button :disabled="!voiceCloneReady">Generate</button>
Type guard
function isVoiceCloneRequestReady(modelId: string, sample: string): boolean {
return modelId !== 'mimo-v2.5-tts-voiceclone' || isDataUri(sample)
} Try / catch
try { return await speechStore.speech(provider, modelToUse, input, voiceToUse, requestConfig) }
catch (error) {
// keep the thrown validation message user-facing: it explains exactly what to provide
showError(errorMessageFrom(error))
} Prevention
- Show the voice-sample input only for the voiceclone model and mark it required.
- Validate data-URI shape on input, not at generate time.
- Default the model to a non-clone variant when no sample exists.
When it happens
Trigger: Choosing `mimo-v2.5-tts-voiceclone` in the model dropdown and pressing Generate without having recorded/pasted a voice sample; voice sample field cleared after switching models; sample containing only whitespace; pasting raw base64 without the `data:audio/...;base64,` prefix (passes the blank check but fails downstream) — this specific message, however, is only the empty-sample case.
Common situations: Users assume voice cloning works from the text prompt or `stylePrompt` alone; switching from a normal TTS model where voice selection comes from the voice list; UI flows that forget to surface the sample input for the clone model.
Related errors
- MiMo voice clone requires a base64 audio sample in data URI
- MiMo voice design requires a style prompt in the user messag
- audio models upstream returned malformed body
- Failed to initialize speech provider
- mutexAcquireTimeout must be a positive finite number
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/e45617ff9678ab69.
Report an issue: GitHub.