Hmbown/CodeWhale · error

Moonshot/Kimi API key not found. Get a key

Error message

Moonshot/Kimi API key not found. Get a key: {}. Run 'codewhale auth set --provider moonshot', set {}, or add [{}] api_key. For a Kimi Code plan key, set [providers.moonshot] base_url = "https://api.kimi.com/coding/v1" and model = "kimi-for-coding".

What it means

Generic Moonshot/Kimi routes require a standard Moonshot platform API key. When no credential is found in overrides, env, config, or the secret store, the resolver bails and also explains how to opt into the Kimi Code plan endpoint if that was the intent.

Solutions

  1. Get a key at the Moonshot/Kimi platform console and run: codewhale auth set --provider moonshot
  2. Set MOONSHOT_API_KEY (or the env var listed by env_vars_label) in the environment that launches codewhale.
  3. Add api_key = "..." under [providers.moonshot] in ~/.codewhale/config.toml.
  4. If you actually have a Kimi Code plan key, set [providers.moonshot] base_url = "https://api.kimi.com/coding/v1" and model = "kimi-for-coding".

Example fix

// before
[providers.moonshot]
model = "kimi-k2-0711-preview"

// after
[providers.moonshot]
model = "kimi-k2-0711-preview"
api_key_env = "MOONSHOT_API_KEY"
Defensive patterns

Strategy: validation

Validate before calling

std::env::var("MOONSHOT_API_KEY")
    .ok()
    .filter(|k| !k.trim().is_empty())
    .ok_or_else(|| "MOONSHOT_API_KEY missing; run codewhale auth set --provider moonshot".to_string())?;

Type guard

fn moonshot_key_ready(env_val: Option<&str>) -> bool {
    env_val.map(|k| k.starts_with("sk-")).unwrap_or(false)
}

Try / catch

match result {
    Err(e) if e.to_string().contains("Moonshot/Kimi API key not found") => {
        eprintln!("run: codewhale auth set --provider moonshot");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Provider is ApiProvider::Moonshot, the base URL is not exactly api.kimi.com/coding/v1, and no API key is present via --api-key, MOONSHOT/KIMI env vars, [providers.moonshot] api_key/api_key_env, or stored auth.

Common situations: Fresh Moonshot account setup; deleting a stored key via logout; intending to use a Kimi Code plan but leaving the default base_url so the plan key is never looked up on the right route.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/config.rs:7375

                    .credential_url()
                    .unwrap_or("https://cloud.siliconflow.com/account/ak"),
                provider.env_vars_label(),
                provider_config_table_name(provider)?
            ),
            ApiProvider::Moonshot => {
                let credential_help =
                    credential_help_for_provider_route(provider, &self.active_route_base_url());
                if moonshot_base_url_is_exact_kimi_code(&self.active_route_base_url()) {
                    anyhow::bail!(
                        "Kimi Code membership-plan API key not found. Get a plan key: {}. This route uses api.kimi.com/coding/v1 and does not import Kimi CLI credentials. Run 'codewhale auth set --provider moonshot', set {}, or add [{}] api_key.",
                        credential_help
                            .credential_url
                            .unwrap_or(KIMI_CODE_MEMBERSHIP_PLAN_CONSOLE_URL),
                        provider.env_vars_label(),
                        provider_config_table_name(provider)?
                    );
                }
                anyhow::bail!(
                    "Moonshot/Kimi API key not found. Get a key: {}. Run 'codewhale auth set --provider moonshot', \
                     set {}, or add [{}] api_key. \
                     For a Kimi Code plan key, set [providers.moonshot] base_url = \
                     \"https://api.kimi.com/coding/v1\" and model = \"kimi-for-coding\".",
                    credential_help
                        .credential_url
                        .unwrap_or("https://platform.kimi.ai/console/api-keys"),
                    provider.env_vars_label(),
                    provider_config_table_name(provider)?
                );
            }
            ApiProvider::Anthropic | ApiProvider::Openmodel => {
                anyhow::bail!("{}", missing_provider_api_key_message(provider)?)
            }
            ApiProvider::OpencodeZen => {
                anyhow::bail!("{}", missing_provider_api_key_message(provider)?)
            }
            ApiProvider::OpenaiCodex => anyhow::bail!(

View on GitHub (pinned to 73e0f67d83)