Hmbown/CodeWhale · error
Speech model cannot be empty
Error message
Speech model cannot be empty
What it means
Input validation in `synthesize_speech`: after the provider gate, the requested model string is trimmed and must be non-empty before the request can be built. This fires before text validation and before any network I/O — purely a caller-input check on `SpeechSynthesisRequest.model`.
Source
Thrown at crates/tui/src/client.rs:2345
///
/// The spoken text is placed in an `assistant` message because Xiaomi
/// MiMo's TTS chat-completions surface expects that shape. The optional
/// `instruction` is a `user` message that controls style, voice design, or
/// voice-clone performance and is not spoken verbatim.
pub async fn synthesize_speech(
&self,
request: SpeechSynthesisRequest,
) -> Result<SpeechSynthesisResponse> {
if self.api_provider != crate::config::ApiProvider::XiaomiMimo {
anyhow::bail!(
"speech synthesis requires provider 'xiaomi-mimo' (current: {})",
self.api_provider.as_str()
);
}
let model = request.model.trim().to_string();
if model.is_empty() {
anyhow::bail!("Speech model cannot be empty");
}
let text = request.text.trim().to_string();
if text.is_empty() {
anyhow::bail!("Speech text cannot be empty");
}
let audio_format = normalize_audio_format(&request.audio_format);
let model = wire_model_for_provider_route(self.api_provider, &self.base_url, &model);
let model_lower = model.to_ascii_lowercase();
let instruction = request
.instruction
.as_deref()
.map(str::trim)
.filter(|value| !value.is_empty());
let voice = request
.voice
.as_deref()
.map(str::trim)View on GitHub (pinned to 8880682c63)
Solutions
- Pass an explicit TTS model id, e.g. `--model xiaomi-mimo-tts` (or the specific MiMo voice model you intend).
- If embedding, default the model in the caller before constructing the request: `let model = request.model.trim(); if model.is_empty() { /* pick default */ }`.
- Check for unset shell variables when scripting (`--model "${TTS_MODEL:?TTS_MODEL not set}"`).
Example fix
# before /speech --model "" "hello" # after /speech --model xiaomi-mimo-tts "hello"
Defensive patterns
Strategy: validation
Validate before calling
fn speech_request_valid(model: &str, text: &str) -> bool {
!model.trim().is_empty() && !text.trim().is_empty()
} Type guard
fn non_blank(s: &str) -> Option<&str> {
let t = s.trim();
(!t.is_empty()).then_some(t)
} Prevention
- Default the TTS model in the command layer when the argument is omitted.
- Validate CLI args (model + text non-blank) before dispatching to the client.
- Use shell parameter expansion guards like `--model "${TTS_MODEL:?unset}"` in scripts.
When it happens
Trigger: Invoking the speech command with no `--model` argument (or a whitespace-only value) when no configured default supplies one; programmatically building a `SpeechSynthesisRequest` with `model: ""` or `" "`.
Common situations: Command-line invocation that assumes a default TTS model exists; UI state where the model selector was left blank; scripts passing an empty variable (`--model "$TTS_MODEL"` with the env var unset).
Related errors
- Speech text cannot be empty
- speech synthesis requires provider 'xiaomi-mimo' (current: {
- Model '{model}' requires a voice design prompt. Pass --voice
- Model '{model}' requires cloned voice data. Pass --clone-voi
- Speech synthesis failed: HTTP {status}: {error_text}
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/64b50651c93342ce.
Report an issue: GitHub.