Hmbown/CodeWhale · error

has no supported external CLI credential source

Error message

{} has no supported external CLI credential source

What it means

Catch-all arm of the external credential target resolver: the provider has no recognized external CLI credential source, so managed import cannot proceed. The message interpolates the provider's string form (e.g. via Display/fmt).

Solutions

  1. Check which providers support external CLI import (`codewhale auth --help` or provider docs)
  2. Authenticate the provider with Codewhale-owned storage: `codewhale auth set --provider <provider>`
  3. If it is a newly added provider, extend external_credential_target's match in crates/cli/src/lib.rs
Defensive patterns

Strategy: validation

Validate before calling

IMPORTABLE_PROVIDERS = {'grok', 'deepseek', 'deepseek-anthropic'};
if provider.toLowerCase() not in IMPORTABLE_PROVIDERS: skip_import(provider)

Try / catch

try { importExternalCredential(provider) } catch (e) { if (String(e).includes('no supported external CLI credential source')) { fallbackToAuthSet(provider); } else { throw e; } }

Prevention

When it happens

Trigger: Calling the external-credential import flow with a ProviderKind that is not one of the explicitly mapped kinds (Grok, Deepseek variants handled; Moonshot rejected with its own message).

Common situations: Adding a new provider to config and assuming import works; typos or aliases resolving to an unmapped kind; scripts looping over all configured providers including ones with no CLI source.

Related errors


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

Appendix: source

Thrown at crates/cli/src/lib.rs:2822

    path_override: Option<PathBuf>,
) -> Result<(codewhale_config::ExternalCredentialSource, PathBuf)> {
    let (source, default_path) = match provider {
        ProviderKind::OpenaiCodex => (
            codewhale_config::ExternalCredentialSource::CodexCli,
            openai_codex_auth_file_path(),
        ),
        ProviderKind::Xai => (
            codewhale_config::ExternalCredentialSource::GrokCli,
            grok_auth_file_path(),
        ),
        ProviderKind::Deepseek | ProviderKind::DeepseekAnthropic => (
            codewhale_config::ExternalCredentialSource::DshCli,
            codewhale_config::default_dsh_credentials_path(),
        ),
        ProviderKind::Moonshot => bail!(
            "Kimi is API-key-only in Codewhale. Create a key at https://platform.kimi.ai/console/api-keys; Kimi CLI OAuth import is unsupported."
        ),
        _ => bail!(
            "{} has no supported external CLI credential source",
            provider.as_str()
        ),
    };
    let path =
        codewhale_config::resolve_external_credential_path(path_override.unwrap_or(default_path))?;
    Ok((source, path))
}

fn provider_config_api_key(store: &ConfigStore, provider: ProviderKind) -> Option<&str> {
    let slot = store
        .config
        .providers
        .for_provider(provider)
        .api_key
        .as_deref();
    let root = (provider == ProviderKind::Deepseek)
        .then_some(store.config.api_key.as_deref())

View on GitHub (pinned to 73e0f67d83)