Hmbown/CodeWhale · error · anyhow::Error

`speech` requires provider = "xiaomi-mimo

Error message

`speech` requires provider = "xiaomi-mimo" (current: {}). Run with `--provider xiaomi-mimo` or set it in config.

What it means

The `speech` (text-to-speech) subcommand only supports the Xiaomi MiMo provider; it bails when the active API provider in the config is anything else. The message names the required provider value and both ways to set it.

Solutions

  1. Re-run with `--provider xiaomi-mimo`
  2. Set provider = "xiaomi-mimo" in the config file
  3. Confirm with `codewhale doctor` or config output which provider is currently active

Example fix

// before
codewhale speech --text "hello"
// after
codewhale --provider xiaomi-mimo speech --text "hello"
// or in config: provider = "xiaomi-mimo"
Defensive patterns

Strategy: validation

Validate before calling

if config.api_provider() != ApiProvider::XiaomiMimo {
    eprintln!("speech requires provider xiaomi-mimo, got {}", config.api_provider().as_str());
    std::process::exit(2);
}

Prevention

When it happens

Trigger: Running the `speech` subcommand while config.api_provider() is not ApiProvider::XiaomiMimo (e.g. another provider is configured or selected via a --provider flag elsewhere).

Common situations: A default config pointing at a different provider; forgetting `--provider xiaomi-mimo` on the command line; a config file where api_provider was set for chat but speech was never switched.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/c85cdbbdda5a7f06. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/lib.rs:7804

        default_speech_output_name, describe_speech_voice, encode_voice_clone_sample_data_uri,
        infer_speech_model, normalize_speech_format,
    };

    let SpeechArgs {
        text,
        output,
        output_dir,
        model,
        voice,
        instruction,
        voice_prompt,
        clone_voice,
        format,
        json: json_output,
    } = args;

    if config.api_provider() != ApiProvider::XiaomiMimo {
        bail!(
            "`speech` requires provider = \"xiaomi-mimo\" (current: {}). Run with `--provider xiaomi-mimo` or set it in config.",
            config.api_provider().as_str()
        );
    }

    if text.trim().is_empty() {
        bail!("Speech text cannot be empty");
    }
    let voice_is_data_uri = voice
        .as_deref()
        .map(str::trim)
        .is_some_and(|value| value.starts_with("data:audio/"));
    if clone_voice.is_some() && voice.is_some() {
        bail!("Use either --clone-voice or --voice for cloned voice data, not both");
    }
    let model = infer_speech_model(
        model.as_deref(),
        clone_voice.is_some() || voice_is_data_uri,

View on GitHub (pinned to 73e0f67d83)