Hmbown/CodeWhale · error

speech synthesis requires provider 'xiaomi-mimo' (current: {

Error message

speech synthesis requires provider 'xiaomi-mimo' (current: {})

What it means

`synthesize_speech` implements Xiaomi MiMo's TTS chat-completions surface and is hard-gated to the `xiaomi-mimo` provider; the very first check compares `self.api_provider` against `ApiProvider::XiaomiMimo` and bails for anything else. The speech tool (`tools/speech.rs`) and the top-level speech command (`lib.rs`) both route through this method.

Source

Thrown at crates/tui/src/client.rs:2337

                        "provider catalog refresh failed; keeping existing rows"
                    );
                }
            }
        });
    }

    /// 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> {
        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

View on GitHub (pinned to 8880682c63)

Solutions

  1. Switch the active provider to xiaomi-mimo (`provider = "xiaomi-mimo"` in config, or the in-app provider switcher) and re-run the speech command.
  2. Use an external TTS integration instead if you need speech on other providers — this client path is Xiaomi MiMo-only by design.
  3. If embedding programmatically, construct the client bound to `ApiProvider::XiaomiMimo` before calling `synthesize_speech`.

Example fix

# before
provider = "deepseek"
# after
provider = "xiaomi-mimo"
Defensive patterns

Strategy: validation

Validate before calling

fn can_synthesize_speech(provider: ApiProvider) -> bool {
    provider == ApiProvider::XiaomiMimo
}

Prevention

When it happens

Trigger: Running the speech-synthesis command while the active provider is `deepseek`, `anthropic`, `openai`, or any custom provider — the request is rejected before model/text validation or any network call.

Common situations: Trying `/speech` or the TTS tool while in a normal coding session on another provider; switching providers in config but expecting TTS to work generically; embedding the client and calling `synthesize_speech` on a general-purpose client.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/478fda91b6c1cacd. Report an issue: GitHub.