Hmbown/CodeWhale · error · anyhow::Error

external credential access for {} is dormant until that prov

Error message

external credential access for {} is dormant until that provider is explicitly selected

What it means

Config::external_credential_read_grant() mints the capability required before any external CLI credential file may be stat/read. It refuses when the requested provider differs from the active api_provider(): access to another CLI's credentials stays dormant until that provider is explicitly selected. This is a deliberate least-privilege gate, not a bug.

Source

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

            })
    }

    /// Mint a read capability for the exact external credential path selected
    /// when consent was granted.
    ///
    /// Path resolution itself is side-effect free. The returned capability is
    /// required by every external credential adapter before it may stat or
    /// read the selected file. `suggested_path` is used only in disabled-mode
    /// guidance; an existing grant remains pinned to its persisted path even
    /// if ambient CLI-home environment variables change later.
    pub(crate) fn external_credential_read_grant(
        &self,
        provider: ApiProvider,
        source: codewhale_config::ExternalCredentialSource,
        suggested_path: &Path,
    ) -> Result<codewhale_config::ExternalCredentialReadGrant> {
        if provider != self.api_provider() {
            anyhow::bail!(
                "external credential access for {} is dormant until that provider is explicitly selected",
                provider.display_name()
            );
        }
        let kind = provider
            .metadata()
            .map(codewhale_config::provider::Provider::kind)
            .context("external credentials are unsupported for this provider")?;
        let consent = self
            .provider_config_for(provider)
            .and_then(|entry| entry.external_credentials.as_ref())
            .with_context(|| {
                format!(
                    "External credentials owned by {} are disabled for {}. To allow read-only access to this exact file, run:\n  codewhale auth external-consent --provider {} --mode read-only --path {}",
                    source.as_str(),
                    provider.display_name(),
                    kind.as_str(),
                    codewhale_config::quote_os_path(suggested_path)

View on GitHub (pinned to 8880682c63)

Solutions

  1. Select the target provider first (provider = in config, or the --provider CLI flag) before requesting its external credentials.
  2. In code, skip the grant when provider != config.api_provider() instead of treating it as an error.
  3. If you only need to know whether consent exists, use external_credential_read_consent_configured(), which never mints a grant and never stats the file.

Example fix

// before
let grant = config.external_credential_read_grant(ApiProvider::Xai, source, &path)?;

// after
if config.api_provider() != ApiProvider::Xai {
    return Ok(None); // external credentials dormant unless provider is selected
}
let grant = config.external_credential_read_grant(ApiProvider::Xai, source, &path)?;
Defensive patterns

Strategy: validation

Validate before calling

// before touching external credentials, gate on the active provider
fn grant_if_active(
    config: &Config,
    provider: ApiProvider,
    source: ExternalCredentialSource,
    path: &Path,
) -> Result<Option<ExternalCredentialReadGrant>> {
    if provider != config.api_provider() {
        return Ok(None); // dormant by design — not an error
    }
    Ok(Some(config.external_credential_read_grant(provider, source, path)?))
}

Type guard

fn provider_credentials_are_eligible(config: &Config, provider: ApiProvider) -> bool {
    config.api_provider() == provider
}

Try / catch

match config.external_credential_read_grant(provider, source, &path) {
    Ok(grant) => Some(grant),
    Err(e) if e.to_string().contains("dormant until that provider is explicitly selected") => {
        None // expected for non-selected providers; do not surface as failure
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling external_credential_read_grant(ApiProvider::Xai, ...) while the active provider is anthropic; provider-picker or diagnostic code probing credentials for every known provider regardless of selection.

Common situations: Bulk credential scans/status pages iterating all providers; code reused from a context where the provider was selected; tests that forget to set the provider before requesting a grant.

Related errors


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