Hmbown/CodeWhale · error · anyhow::Error

external credential path changed for {}; consent covers {},

Error message

external credential path changed for {}; consent covers {}, current path is {}

What it means

Thrown by ExternalCredentialConsentToml::validate_read_scope (crates/config/src/external_credentials.rs:448) when the persisted read-only consent record pins a different absolute path than the credential path the caller currently resolves. Consent is deliberately scoped to one exact provider/source/path tuple, so any drift fails closed instead of silently granting read access to a new file. The record itself is untouched; only the capability check fails.

Source

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

                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)
            );
        }
        if self.path != resolved_path {
            bail!(
                "external credential path changed for {}; consent covers {}, current path is {}",
                provider.as_str(),
                quote_os_path(&self.path),
                quote_os_path(resolved_path)
            );
        }
        Ok(())
    }

    /// Validate and mint the read capability consumed by credential adapters.
    /// No filesystem operation occurs while validating the policy.
    pub fn read_grant(
        &self,
        provider: ProviderKind,
        source: ExternalCredentialSource,
        resolved_path: &Path,
    ) -> Result<ExternalCredentialReadGrant> {
        self.validate_read_scope(provider, source, resolved_path)?;

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Re-run the consent flow for the provider so the record stores the current resolved path (after it, validate covers the new file)
  2. If the old file is still the intended one, point the source env var/config back to the consented path shown in the message (consent covers <old>, current path is <new>)
  3. Run `codewhale auth external-revoke --provider <provider>` if you want to clear the stale consent before re-consenting
  4. Check the consent status surface (ambient_path_changed field in ExternalCredentialConsentStatus) to confirm the drift before acting

Example fix

# before
export MY_PROVIDER_CREDENTIALS=/home/me/creds/old-key.json   # consent covers this
mv /home/me/creds/old-key.json /home/me/creds/new-key.json
# read_grant -> path changed for <provider>

# after
export MY_PROVIDER_CREDENTIALS=/home/me/creds/new-key.json
codewhale auth external-revoke --provider <provider>
# re-run the external-credential consent flow so consent covers new-key.json
Defensive patterns

Strategy: validation

Validate before calling

// before read_grant, compare the consent record path with the currently resolved path
let consent: &ExternalCredentialConsentToml = /* loaded */;
if consent.path != resolved_path {
    // re-run the consent flow instead of calling read_grant
}

Try / catch

match consent.read_grant(provider, source, &resolved_path) {
    Ok(grant) => { /* use grant */ }
    Err(e) if e.to_string().contains("external credential path changed") => { /* prompt re-consent */ }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling validate_read_scope or read_grant with a resolved_path that differs from self.path (the absolute, lexically normalized consented path): the env var backing the credential source was repointed, the credential file was moved/renamed, HOME or the workspace changed the resolution, or the provider table was copied to another machine with different layout.

Common situations: Rotating service-account files (new filename, old consent), syncing dotfiles between machines, CI with a different HOME, re-arranging ~/.config or a credentials directory after running the consent flow once.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/442e6974f098b88f. Report an issue: GitHub.