Hmbown/CodeWhale · error

Kimi CLI credentials are never imported; configure a Kimi…

Error message

Kimi CLI credentials are never imported; configure a Kimi API key instead

What it means

The external-credential resolver never imports Kimi CLI credentials: `KimiCodeCli` is accepted by the enum but its match arm immediately fails with this error. Users must configure a Kimi API key directly rather than importing credentials from the Kimi CLI.

Solutions

  1. Configure a Kimi API key directly (provider config key / `codewhale auth save --provider kimi ...`)
  2. Remove the Kimi CLI entry from `external_credentials` in your config

Example fix

// before
[external_credentials]
provider = "kimi"
source = "kimi-cli"
// after
# delete block; save a Kimi API key instead
codewhale auth save --provider kimi --api-key <key>
Defensive patterns

Strategy: validation

Validate before calling

if source == ExternalCredentialSource::KimiCodeCli {
    eprintln!("configure a Kimi API key directly instead of CLI import");
}

Type guard

fn kimi_uses_api_key(p: ApiProvider) -> bool { p == ApiProvider::Kimi }

Try / catch

match resolve_result {
    Err(e) if e.to_string().contains("Kimi CLI credentials") => configure_kimi_api_key(),
    other => other?,
}

Prevention

When it happens

Trigger: Resolving external credentials where the stored source is `ExternalCredentialSource::KimiCodeCli`, i.e. a consent record or config pointing at the Kimi CLI as a credential source.

Common situations: Config that names the Kimi CLI as an external credential owner; copying an external-credentials block from another provider (e.g. Codex CLI) to Kimi.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

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

    .read_grant(consent_provider, source, path)?;
    match source {
        codewhale_config::ExternalCredentialSource::CodexCli => {
            crate::oauth::get_credentials(&grant).map(|_| ())
        }
        codewhale_config::ExternalCredentialSource::GrokCli => {
            crate::oauth::validate_grok_external_credentials(&grant)
        }
        codewhale_config::ExternalCredentialSource::DshCli => {
            crate::dsh_credentials::deepseek_api_key_from_grant(&grant)?
                .map(|_| ())
                .context("the DeepSeek Harness credentials file holds no DEEPSEEK_API_KEY")
        }
        // Retired: the reader is gone, so a legacy consent record validates
        // to nothing rather than resolving a route (PRD §4.4 PROD-002).
        codewhale_config::ExternalCredentialSource::AgyCli => {
            anyhow::bail!(codewhale_config::LEGACY_ANTIGRAVITY_TOMBSTONE_MESSAGE)
        }
        codewhale_config::ExternalCredentialSource::KimiCodeCli => anyhow::bail!(
            "Kimi CLI credentials are never imported; configure a Kimi API key instead"
        ),
    }
}

/// Persist an explicitly confirmed read-only external credential grant and
/// update the live mirror only after the comment-preserving disk mutation
/// succeeds.
///
/// Order is load-bearing (#5772): the caller has already shown the
/// confirmation disclosure, this function then reads and validates the exact
/// consented file, and only a usable credential is allowed to produce a
/// persisted consent record.
pub(crate) fn persist_external_credential_consent_for_at(
    config_path: Option<&Path>,
    live_config: &mut Config,
    provider: ApiProvider,
    consent_provider: codewhale_config::ProviderKind,

View on GitHub (pinned to 73e0f67d83)