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

  1. Switch the active provider/route to xiaomi-mimo (or configure the route so speech requests resolve to it), then retry.
  2. Configure the model route so the speech model maps to provider xiaomi-mimo.
  3. 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

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


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 = request

View on GitHub (pinned to 73e0f67d83)