Hmbown/CodeWhale · error · anyhow::Error
speech synthesis requires provider 'xiaomi-mimo
Error message
speech synthesis requires provider 'xiaomi-mimo' (current: {}) What it means
Speech synthesis (TTS) is only implemented for the xiaomi-mimo provider. If `synthesize_speech` is called while the client is bound to any other ApiProvider, it bails naming the required and current provider.
Solutions
- Switch the active provider/route to xiaomi-mimo (or configure the route so speech requests resolve to it), then retry.
- Configure the model route so the speech model maps to provider xiaomi-mimo.
- If you expected TTS support on your provider, use a provider that implements it.
Defensive patterns
Strategy: validation
Validate before calling
fn ensure_speech_provider(client: &Client) -> Result<(), String> {
if client.api_provider != ApiProvider::XiaomiMimo {
return Err(format!("speech synthesis needs provider xiaomi-mimo, current: {}", client.api_provider.as_str()));
}
Ok(())
} Type guard
fn supports_speech(p: &ApiProvider) -> bool { matches!(p, ApiProvider::XiaomiMimo) } Try / catch
match result {
Err(e) if e.to_string().contains("requires provider 'xiaomi-mimo'") => {
eprintln!("Switch provider to xiaomi-mimo before using speech synthesis");
}
r => r?,
} Prevention
- Gate TTS commands behind a provider check in the UI/CLI.
- Configure the speech model route to resolve to xiaomi-mimo.
- Show available capabilities per provider to users before invoking commands.
When it happens
Trigger: Calling the speech synthesis client method (with request and rate permits acquired) when `self.api_provider != ApiProvider::XiaomiMimo` — i.e. the active provider/route is not xiaomi-mimo.
Common situations: Running a TTS slash command while the session's provider is openai/anthropic; a config route defaulting to another provider; forgetting to switch provider before invoking speech synthesis.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Failed to resolve runtime thread route
- Fleet task ` ` has no provider authority for model ` `…
- Fleet task ` ` names custom provider=` `, but a provider…
- saved cache route identity
- `speech` requires provider = "xiaomi-mimo
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/478fda91b6c1cacd.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/client.rs:3324
}
});
}
}
/// Generate speech with Xiaomi MiMo TTS models.
///
/// 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> {
let _inference = self.acquire_remote_control_inference_permit().await;
let _permit = self.acquire_provider_request_permit().await;
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 = self.wire_model_for_route(&model);
let model_lower = model.to_ascii_lowercase();
let instruction = requestView on GitHub (pinned to 73e0f67d83)