{"record":{"id":"51ec4d88d813abaf","repo":"Hmbown/CodeWhale","slug":"speech-requires-a-tts-model-examples-got-m","errorCode":null,"errorMessage":"speech requires a TTS model (examples: {}); got {model}","messagePattern":"speech requires a TTS model \\(examples: (.+?)\\); got (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/lib.rs","lineNumber":7827,"sourceCode":"\n    if text.trim().is_empty() {\n        bail!(\"Speech text cannot be empty\");\n    }\n    let voice_is_data_uri = voice\n        .as_deref()\n        .map(str::trim)\n        .is_some_and(|value| value.starts_with(\"data:audio/\"));\n    if clone_voice.is_some() && voice.is_some() {\n        bail!(\"Use either --clone-voice or --voice for cloned voice data, not both\");\n    }\n    let model = infer_speech_model(\n        model.as_deref(),\n        clone_voice.is_some() || voice_is_data_uri,\n        voice_prompt.is_some(),\n    );\n    let model_lower = model.to_ascii_lowercase();\n    if !model_lower.contains(\"tts\") {\n        bail!(\n            \"speech requires a TTS model (examples: {}); got {model}\",\n            SPEECH_MODEL_EXAMPLES.join(\", \")\n        );\n    }\n    let is_voice_design = model_lower.contains(\"voicedesign\");\n    let is_voice_clone = model_lower.contains(\"voiceclone\");\n\n    let instruction = combine_speech_instructions(instruction, voice_prompt);\n    if is_voice_design\n        && instruction\n            .as_deref()\n            .is_none_or(|value| value.trim().is_empty())\n    {\n        bail!(\n            \"mimo-v2.5-tts-voicedesign requires --voice-prompt or --instruction to describe the voice\"\n        );\n    }\n","sourceCodeStart":7809,"sourceCodeEnd":7845,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/lib.rs#L7809-L7845","documentation":"The speech subcommand requires a text-to-speech model; after inferring the model (from --model or defaults based on voice/voice-prompt usage), it checks the lowercase model name contains \"tts\" and bails otherwise, listing example TTS model names from SPEECH_MODEL_EXAMPLES.","triggerScenarios":"Passing --model with a non-TTS model name (e.g. a chat model like mimo-v2.5) to `speech`, or a config default model that is not a TTS model.","commonSituations":"Reusing a chat model name from the speech command line; typos in the TTS model id; stale config defaults where the general model leaks into the speech command.","solutions":["Pass an explicit TTS model via --model (see the example names in the error message)","Use a model name containing \"tts\", e.g. mimo-v2.5-tts or the voicedesign/voiceclone variants","Fix the config default model so it does not supply a chat model to speech"],"exampleFix":"// before\ncodewhale speech --model mimo-v2.5 --text \"hi\"\n// after\ncodewhale speech --model mimo-v2.5-tts --text \"hi\"","handlingStrategy":"validation","validationCode":"if !model.to_ascii_lowercase().contains(\"tts\") {\n    eprintln!(\"speech requires a TTS model, got {model}\");\n    std::process::exit(2);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep a constant list of valid TTS model ids in tooling","Never reuse chat model defaults for the speech subcommand","Validate --model values against SPEECH_MODEL_EXAMPLES in CI scripts"],"tags":["cli","speech","model","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}