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
- Revoke the existing consent and run the consent flow again so the record's source matches the current read.
- Check which source produced the current credential and read via that same source.
- 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
- Read credentials through the same source that produced them at consent time.
- Re-consent whenever the credential acquisition method changes.
- Do not hand-edit the `source` field of consent records.
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
- external credential consent is scoped to provider
- api_key cannot be empty string
- external credential consent for
- external credential consent path for
- external credential consent path for
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)