Hmbown/CodeWhale · error · anyhow::Error
speech requires a TTS model (examples: {}); got {model}
Error message
speech requires a TTS model (examples: {}); got {model} What it means
Model sanity check for speech: infer_speech_model() resolves the model (an explicit `--model` normalized for Xiaomi MiMo, or an inferred default from --clone-voice/--voice-prompt), and the resolved name must contain "tts" (lowercased substring test). Any other value — typically a chat model name typed into `--model` — is rejected with the list of valid examples before a request is made.
Source
Thrown at crates/tui/src/lib.rs:7378
if text.trim().is_empty() {
bail!("Speech text cannot be empty");
}
let voice_is_data_uri = voice
.as_deref()
.map(str::trim)
.is_some_and(|value| value.starts_with("data:audio/"));
if clone_voice.is_some() && voice.is_some() {
bail!("Use either --clone-voice or --voice for cloned voice data, not both");
}
let model = infer_speech_model(
model.as_deref(),
clone_voice.is_some() || voice_is_data_uri,
voice_prompt.is_some(),
);
let model_lower = model.to_ascii_lowercase();
if !model_lower.contains("tts") {
bail!(
"speech requires a TTS model (examples: {}); got {model}",
SPEECH_MODEL_EXAMPLES.join(", ")
);
}
let is_voice_design = model_lower.contains("voicedesign");
let is_voice_clone = model_lower.contains("voiceclone");
let instruction = combine_speech_instructions(instruction, voice_prompt);
if is_voice_design
&& instruction
.as_deref()
.is_none_or(|value| value.trim().is_empty())
{
bail!(
"mimo-v2.5-tts-voicedesign requires --voice-prompt or --instruction to describe the voice"
);
}
View on GitHub (pinned to 0c42157ee5)
Solutions
- Use one of the TTS models: mimo-v2.5-tts, mimo-v2.5-tts-voicedesign, mimo-v2.5-tts-voiceclone, or mimo-v2-tts
- Or omit `--model` entirely and let the CLI infer it from --clone-voice / --voice-prompt
- Check the exact string for typos — the match is a substring test on the lowercased name
Example fix
// before $ codewhale speech --model mimo-v2.5 ... Error: speech requires a TTS model (examples: mimo-v2.5-tts, ...); got mimo-v2.5 // after $ codewhale speech --model mimo-v2.5-tts ... // or drop --model: the right TTS variant is inferred from the flags
Defensive patterns
Strategy: validation
Validate before calling
# mirror the CLI check before invoking m=$(printf '%s' "$MODEL" | tr '[:upper:]' '[:lower:]') case "$m" in *tts*) ;; *) echo "not a TTS model: $MODEL" >&2; exit 2;; esac
Prevention
- Keep speech models in a dedicated variable; never share the chat MODEL var
- Prefer omitting --model so inference picks a valid TTS variant
When it happens
Trigger: Passing an explicit `--model` whose (normalized) name lacks "tts", e.g. `--model mimo-v2.5` or a DeepSeek chat model. Omitting --model never triggers this: inference yields mimo-v2.5-tts, mimo-v2.5-tts-voiceclone, or mimo-v2.5-tts-voicedesign.
Common situations: Reusing a chat model name from muscle memory; a typo in the model string; scripts where MODEL was set for coding, not speech.
Related errors
- speech synthesis requires provider 'xiaomi-mimo' (current: {
- Speech model cannot be empty
- Speech text cannot be empty
- `speech` requires provider = "xiaomi-mimo" (current: {}). Ru
- Speech text cannot be empty
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/51ec4d88d813abaf.
Report an issue: GitHub.