Hmbown/CodeWhale · error · anyhow::Error

Kimi Code membership-plan API key not found. Get a plan key:

Error message

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.

What it means

Raised for ApiProvider::Moonshot when the base URL is exactly the Kimi Code membership endpoint (https://api.kimi.com/coding/v1) and no plan key is configured. This route never imports Kimi CLI credentials; it requires a membership-plan API key, so the generic Moonshot guidance is replaced with plan-specific instructions.

Source

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

                   • api_key = \"<your-key>\"  in ~/.codewhale/config.toml\n\
                   • already configured DeepSeek Harness? grant read-only access:\n\
                        codewhale auth external-consent --provider deepseek --mode read-only"
            ),
            ApiProvider::SiliconflowCn => anyhow::bail!(
                "SiliconFlow China API key not found. Get a key: {}. Run 'codewhale auth set --provider siliconflow-CN', \
                 set {}, or add [{}] api_key in ~/.codewhale/config.toml. \
                 [providers.siliconflow] remains a fallback when the CN table omits api_key.",
                provider
                    .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)?

View on GitHub (pinned to 8880682c63)

Solutions

  1. Get a plan key from the Kimi console URL shown in the message.
  2. Run codewhale auth set --provider moonshot.
  3. Or export the Moonshot env var shown in the message.
  4. Or add api_key under [providers.moonshot].

Example fix

# before
[providers.moonshot]
base_url = "https://api.kimi.com/coding/v1"
model = "kimi-for-coding"
# no plan key configured

# after
[providers.moonshot]
base_url = "https://api.kimi.com/coding/v1"
model = "kimi-for-coding"
api_key = "<plan-key>"
Defensive patterns

Strategy: validation

Validate before calling

fn kimi_code_route(cfg: &Config) -> bool {
    moonshot_base_url_is_exact_kimi_code(&cfg.deepseek_base_url())
}

if kimi_code_route(&config) {
    anyhow::ensure!(
        moonshot_key_present(&config),
        "Kimi Code route requires a membership-plan key (not a Kimi CLI login)"
    );
}

Type guard

fn is_kimi_code_membership_route(cfg: &Config) -> bool {
    moonshot_base_url_is_exact_kimi_code(&cfg.deepseek_base_url())
}

Try / catch

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

Prevention

When it happens

Trigger: [providers.moonshot] base_url = "https://api.kimi.com/coding/v1" (exact match via moonshot_base_url_is_exact_kimi_code) with no stored key, env var, or api_key; users switching from pay-as-you-go Moonshot to a Kimi Code subscription without rotating credentials.

Common situations: Subscribing to Kimi Code membership and following the base_url/model switch steps but skipping the key step; mixing Kimi CLI login (OAuth) expectations with the plan-key route.

Related errors


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