Hmbown/CodeWhale · error

has no supported external credential owner

Error message

{} has no supported external credential owner

What it means

When reconciling an external-consent grant, the provider-to-(kind, source) mapping only covers providers with a supported external credential owner (Codex CLI, Grok CLI, etc.). Any other provider hits the `_` catch-all arm, which bails stating that the provider has no supported external credential owner.

Solutions

  1. Only grant external consent for providers with an external CLI owner (e.g. openai-codex via Codex CLI, xai via Grok CLI)
  2. For other providers, save an API key directly instead of using external-consent

Example fix

// before
codewhale auth external-consent --provider anthropic --mode read-only
// after
codewhale auth save --provider anthropic --api-key <key>
Defensive patterns

Strategy: validation

Validate before calling

let supported = matches!(provider, ApiProvider::OpenaiCodex | ApiProvider::Xai);
if !supported { eprintln!("{} has no external credential owner", provider.as_str()); }

Type guard

fn has_external_owner(p: ApiProvider) -> bool {
    matches!(p, ApiProvider::OpenaiCodex | ApiProvider::Xai)
}

Try / catch

match consent_result {
    Err(e) if e.to_string().ends_with("no supported external credential owner") => save_api_key_directly(provider),
    other => other?,
}

Prevention

When it happens

Trigger: Calling the external-consent/credential-owner resolution with an `ApiProvider` that has no match arm (e.g. a native API-key provider like Anthropic, DeepSeek, or a custom provider) while expecting an external CLI source.

Common situations: Running `codewhale auth external-consent --provider <name>` for a provider that does not support CLI-based consent; generic automation iterating all providers and calling the consent routine on each.

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/be2f871b212dae74. Report an issue: GitHub.

Appendix: source

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

/// 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,
    source: codewhale_config::ExternalCredentialSource,
    path: &Path,
) -> Result<PathBuf> {
    let expected = match provider {
        ApiProvider::OpenaiCodex => (
            codewhale_config::ProviderKind::OpenaiCodex,
            codewhale_config::ExternalCredentialSource::CodexCli,
        ),
        ApiProvider::Xai => (
            codewhale_config::ProviderKind::Xai,
            codewhale_config::ExternalCredentialSource::GrokCli,
        ),
        _ => anyhow::bail!(
            "{} has no supported external credential owner",
            provider.as_str()
        ),
    };
    anyhow::ensure!(
        (consent_provider, source) == expected,
        "external credential owner does not match provider {}",
        provider.as_str()
    );
    let path = codewhale_config::resolve_external_credential_path(path)?;
    let path_value = path.to_str().context(
        "external credential path cannot be persisted losslessly because it is not valid UTF-8",
    )?;
    validate_external_credential_before_consent(consent_provider, source, &path).with_context(
        || {
            format!(
                "no usable {} credential was found, so read-only consent was not saved",
                source.owner_label()

View on GitHub (pinned to 73e0f67d83)