Hmbown/CodeWhale · error

external credential consent source mismatch for

Error message

external credential consent source mismatch for {} (expected {})

What it means

Thrown by `ExternalCredentialConsentToml::validate_read_scope` when the consent record's `source` field does not equal the source argument of the read. A consent grant is bound to both a provider and a source (where the credential came from), so a grant issued for one source cannot authorize a read attributed to another.

Solutions

  1. Revoke the existing consent and run the consent flow again so the record's source matches the current read.
  2. Check which source produced the current credential and read via that same source.
  3. Inspect the consent TOML's `source` field and correct the caller's source argument if it is wrong.
Defensive patterns

Strategy: validation

Validate before calling

fn consent_source_matches(consent: &ExternalCredentialConsentToml, source: &CredentialSource) -> bool {
    consent.source == *source
}

Try / catch

match store.read_grant(provider, source, &path) {
    Err(e) if e.to_string().contains("source mismatch") => {
        // re-consent so the recorded source matches the credential's actual source
        store.revoke(provider)?;
        run_consent_flow(provider)?;
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling `read_grant` with a `source` argument whose `as_str()` differs from `self.source` on the stored consent record — e.g. credential obtained from OAuth vs an API key import but consent recorded for the other source.

Common situations: The credential's acquisition path changed between consent and use (user re-authenticated via a different source); a consent record was hand-edited; a new source variant was introduced and old consents were recorded under a different source string.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at crates/config/src/external_credentials.rs:389

                provider.as_str()
            );
        }
        if self.consent_version != EXTERNAL_CREDENTIAL_CONSENT_VERSION {
            bail!(
                "external credential consent for {} uses unsupported version {}; revoke and consent again",
                provider.as_str(),
                self.consent_version
            );
        }
        if self.provider != provider.as_str() {
            bail!(
                "external credential consent is scoped to provider {:?}, not {}",
                self.provider,
                provider.as_str()
            );
        }
        if self.source != source {
            bail!(
                "external credential consent source mismatch for {} (expected {})",
                provider.as_str(),
                source.as_str()
            );
        }
        if !self.path.is_absolute() {
            bail!(
                "external credential consent path for {} must be absolute",
                provider.as_str()
            );
        }
        let normalized = resolve_external_credential_path(&self.path)?;
        if normalized != self.path {
            bail!(
                "external credential consent path for {} must be lexically normalized: {}",
                provider.as_str(),
                quote_os_path(&self.path)
            );

View on GitHub (pinned to 73e0f67d83)