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

  1. Use one of the TTS models: mimo-v2.5-tts, mimo-v2.5-tts-voicedesign, mimo-v2.5-tts-voiceclone, or mimo-v2-tts
  2. Or omit `--model` entirely and let the CLI infer it from --clone-voice / --voice-prompt
  3. 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

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


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/51ec4d88d813abaf. Report an issue: GitHub.