{"record":{"id":"478fda91b6c1cacd","repo":"Hmbown/CodeWhale","slug":"speech-synthesis-requires-provider-xiaomi-mimo","errorCode":null,"errorMessage":"speech synthesis requires provider 'xiaomi-mimo' (current: {})","messagePattern":"speech synthesis requires provider 'xiaomi-mimo' \\(current: (.+?)\\)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/client.rs","lineNumber":3324,"sourceCode":"                }\n            });\n        }\n    }\n\n    /// Generate speech with Xiaomi MiMo TTS models.\n    ///\n    /// The spoken text is placed in an `assistant` message because Xiaomi\n    /// MiMo's TTS chat-completions surface expects that shape. The optional\n    /// `instruction` is a `user` message that controls style, voice design, or\n    /// voice-clone performance and is not spoken verbatim.\n    pub async fn synthesize_speech(\n        &self,\n        request: SpeechSynthesisRequest,\n    ) -> Result<SpeechSynthesisResponse> {\n        let _inference = self.acquire_remote_control_inference_permit().await;\n        let _permit = self.acquire_provider_request_permit().await;\n        if self.api_provider != crate::config::ApiProvider::XiaomiMimo {\n            anyhow::bail!(\n                \"speech synthesis requires provider 'xiaomi-mimo' (current: {})\",\n                self.api_provider.as_str()\n            );\n        }\n\n        let model = request.model.trim().to_string();\n        if model.is_empty() {\n            anyhow::bail!(\"Speech model cannot be empty\");\n        }\n        let text = request.text.trim().to_string();\n        if text.is_empty() {\n            anyhow::bail!(\"Speech text cannot be empty\");\n        }\n\n        let audio_format = normalize_audio_format(&request.audio_format);\n        let model = self.wire_model_for_route(&model);\n        let model_lower = model.to_ascii_lowercase();\n        let instruction = request","sourceCodeStart":3306,"sourceCodeEnd":3342,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/client.rs#L3306-L3342","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"fn ensure_speech_provider(client: &Client) -> Result<(), String> {\n    if client.api_provider != ApiProvider::XiaomiMimo {\n        return Err(format!(\"speech synthesis needs provider xiaomi-mimo, current: {}\", client.api_provider.as_str()));\n    }\n    Ok(())\n}","typeGuard":"fn supports_speech(p: &ApiProvider) -> bool { matches!(p, ApiProvider::XiaomiMimo) }","tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"requires provider 'xiaomi-mimo'\") => {\n        eprintln!(\"Switch provider to xiaomi-mimo before using speech synthesis\");\n    }\n    r => r?,\n}","preventionTips":["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."],"tags":["speech","tts","provider","routing"],"backgroundTag":"unsupported-operation","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"}