Hmbown/CodeWhale · error · anyhow::Error

Moonshot/Kimi API key not found. Get a key: {}. Run 'codewha

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

The generic Moonshot/Kimi missing-key error, emitted when the base URL is NOT the exact Kimi Code endpoint. It lists the credential URL, the auth-set command, the env var, the config table, and finally the recipe to switch to the Kimi Code plan route (base_url + model = kimi-for-coding).

Source

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

                    .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.deepseek_base_url());
                if moonshot_base_url_is_exact_kimi_code(&self.deepseek_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!("{}", crate::oauth::missing_auth_message()),

View on GitHub (pinned to 8880682c63)

Solutions

  1. Run codewhale auth set --provider moonshot.
  2. Or export the Moonshot env var shown in the message.
  3. Or add api_key under [providers.moonshot] in ~/.codewhale/config.toml.
  4. If you actually hold a Kimi Code plan key, set [providers.moonshot] base_url = "https://api.kimi.com/coding/v1" and model = "kimi-for-coding" instead.

Example fix

# before
provider = "moonshot"
# no key anywhere

# after (terminal)
# codewhale auth set --provider moonshot
# or config:
# [providers.moonshot]
# api_key = "sk-..."
Defensive patterns

Strategy: validation

Validate before calling

fn moonshot_key_present(cfg: &Config) -> bool {
    env_nonempty("MOONSHOT_API_KEY") // or the env vars named by provider.env_vars_label()
        || cfg.provider_config_for(ApiProvider::Moonshot)
            .and_then(|pc| pc.api_key)
            .is_some_and(|k| !k.trim().is_empty())
        || secret_store_has(ApiProvider::Moonshot)
}

anyhow::ensure!(moonshot_key_present(&config), "configure Moonshot auth first");

Type guard

fn moonshot_credentials_configured(cfg: &Config) -> bool {
    moonshot_key_present(cfg)
}

Try / catch

match config.deepseek_api_key() {
    Err(e) if e.to_string().starts_with("Moonshot/Kimi API key not found") => {
        run_auth_set(ApiProvider::Moonshot)?;
        config.deepseek_api_key()
    }
    other => other,
}

Prevention

When it happens

Trigger: provider = moonshot with the default platform endpoint and no stored key, env var, or [providers.moonshot] api_key.

Common situations: First-time Moonshot users; keys cleared by logout or rotated; teams whose CI lacks the MOONSHOT_API_KEY-style secret.

Related errors


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