Hmbown/CodeWhale · error
Kimi CLI credential import is unsupported. Codewhale does…
Error message
Kimi CLI credential import is unsupported. Codewhale does not impersonate or reuse Kimi OAuth clients; configure an API key from {} instead. What it means
Codewhale refuses to route requests through Kimi CLI imported OAuth tokens. The library deliberately does not impersonate or reuse the Kimi CLI's OAuth client, so if the active provider route is configured to use an imported Kimi token, configuration resolution fails fast before any request is sent, pointing the user at the provider's API-key console instead.
Solutions
- Remove the Kimi CLI credential import / imported-token auth_mode from the provider route config.
- Create a Kimi (Moonshot) API key at the console URL shown in the error and set [providers.<route>] api_key or api_key_env.
- Run 'codewhale auth set --provider moonshot' to store the key.
- For Kimi Code plans, set [providers.moonshot] base_url = "https://api.kimi.com/coding/v1" and model = "kimi-for-coding" with a plan API key.
Example fix
// before [providers.moonshot] auth_mode = "kimi-cli-import" // after [providers.moonshot] api_key = "sk-..."
Defensive patterns
Strategy: validation
Validate before calling
fn uses_kimi_import(cfg: &toml::Value) -> bool {
cfg.get("providers").and_then(|p| p.get("moonshot"))
.and_then(|m| m.get("auth_mode"))
.and_then(|a| a.as_str())
.map(|s| s.contains("kimi-cli-import"))
.unwrap_or(false)
}
if uses_kimi_import(load_config()) {
eprintln!("replace the kimi CLI import with api_key before starting");
} Type guard
fn has_static_key(cfg: &ProviderCfg) -> bool {
cfg.api_key.as_deref().map(|k| !k.trim().is_empty()).unwrap_or(false)
|| cfg.api_key_env.as_deref().map(|e| !e.trim().is_empty()).unwrap_or(false)
} Prevention
- Never configure Kimi CLI OAuth import; Codewhale does not reuse third-party OAuth clients.
- Provision a real API key per provider route before enabling it.
- Keep provider credentials as api_key/api_key_env, not imported tokens.
When it happens
Trigger: The active provider route's provider config satisfies provider_config_uses_kimi_imported_token (e.g. [providers.moonshot] configured to import the Kimi CLI token) and any API call resolves credentials through Config::active_route_api_key.
Common situations: A user who previously authenticated with Kimi CLI copies that setup into their codewhale config expecting SSO to carry over; CI or dotfiles migrate a Kimi CLI credential import left over from an older codewhale version that tolerated it.
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
- a CNB access token is not configured in the Codewhale…
- agy OAuth token JSON carries no access token member
- agy OAuth token member
- api_key cannot be empty string
- atomically replacing xAI OAuth credentials
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/9bcd168a9c1d7a3f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/config.rs:7136
}
if matches!(provider, ApiProvider::Deepseek | ApiProvider::DeepseekCN)
&& self.config_credentials_are_bound_to_provider_endpoint(provider)
&& let Some(configured) = self.api_key.as_ref()
&& classify_config_api_key_value(configured) == ConfigApiKeyValueKind::Literal
{
warn_on_config_api_key_shadowing(self, provider, "the root api_key");
return Ok(configured.clone());
}
if provider == ApiProvider::Moonshot
&& !custom_endpoint
&& self
.provider_config_for(provider)
.is_some_and(provider_config_uses_kimi_imported_token)
{
let credential_help =
credential_help_for_provider_route(provider, &self.active_route_base_url());
anyhow::bail!(
"Kimi CLI credential import is unsupported. Codewhale does not impersonate or reuse Kimi OAuth clients; configure an API key from {} instead.",
credential_help
.credential_url
.unwrap_or("the selected provider's API-key console")
);
}
// xAI OAuth prefers Codewhale-owned device-login storage. An existing
// Grok CLI file is considered only with provider/path-scoped read-only
// consent. Activated by [providers.xai] auth_mode = "oauth".
if provider == ApiProvider::Xai
&& !custom_endpoint
&& self
.provider_config_for(provider)
.is_some_and(provider_config_uses_xai_oauth)
&& crate::oauth::credentials_present(crate::oauth::OAuthProvider::Xai, self)
{
return crate::oauth::get_xai_access_token(self);View on GitHub (pinned to 73e0f67d83)