Hmbown/CodeWhale · error
external credential consent is scoped to provider
Error message
external credential consent is scoped to provider {:?}, not {} What it means
Thrown by `ExternalCredentialConsentToml::validate_read_scope` when a stored consent record names a different provider than the one whose credentials are being read. Consent grants are provider-scoped; a record created for one provider can never authorize a read for another. This is a safety check preventing a consent record from being replayed across providers.
Solutions
- Re-run the consent flow for the provider you are actually reading so a correctly-scoped consent record is created.
- Revoke the stale consent (delete the consent record) and consent again with the matching provider.
- Verify the provider argument passed to read_grant/consent-status matches the provider the user actually consented to.
Example fix
// before: reading google creds with an antigravity-scoped consent let grant = store.read_grant(ProviderKind::Google, source, &path)?; // after: revoke the stale record and re-consent for google, or pass // the provider the consent was actually created for let grant = store.read_grant(ProviderKind::Antigravity, source, &path)?;
Defensive patterns
Strategy: validation
Validate before calling
fn consent_matches(consent: &ExternalCredentialConsentToml, provider: ProviderKind) -> bool {
consent.provider == provider.as_str()
} Try / catch
match store.read_grant(provider, source, &path) {
Ok(grant) => use_grant(grant),
Err(e) if e.to_string().contains("scoped to provider") => {
// stale consent for another provider: revoke and re-run consent flow
store.revoke(provider)?;
run_consent_flow(provider)?;
}
Err(e) => return Err(e),
} Prevention
- Always re-run the consent flow after changing which provider is used.
- Never copy consent records between provider sections.
- Remove legacy provider identifiers (e.g. antigravity) from config and re-consent under the current provider.
When it happens
Trigger: Calling `read_grant` (directly or via `external_credential_consent_status`) with a `provider` argument whose `as_str()` differs from the `provider` field persisted in the consent record.
Common situations: A consent file created for one provider (e.g. "google") is being consulted for another (e.g. "openrouter") after a config rename or copy; a user manually edited or moved a consent TOML between provider sections; provider identifier changed (e.g. legacy "antigravity" vs "google") but the old consent record remains.
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 source mismatch for
- 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/621c0891340a01d2.
Report an issue: GitHub.
Appendix: source
Thrown at crates/config/src/external_credentials.rs:382
"external credential access is disabled for {}",
provider.as_str()
);
}
if self.access == ExternalCredentialAccess::Managed {
bail!(
"managed external credential access is unsupported for {}; no schema-safe preservation adapter is available",
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()
);
}View on GitHub (pinned to 73e0f67d83)