Hmbown/CodeWhale · error · anyhow::Error

external credential consent path for {} must be absolute

Error message

external credential consent path for {} must be absolute

What it means

validate_read_scope() requires the consented external-credential path to be absolute before normalization is even attempted; a relative path cannot define the exact file the read-only capability covers, so it is rejected outright.

Source

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

                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)
            );
        }
        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)

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Store the fully expanded absolute path in the consent (expand ~ yourself, e.g. /home/me/keys/acme.env)
  2. Re-create the consent pointing at the absolute location of the credential file

Example fix

# before
path = "~/keys/acme.env"

# after
path = "/home/me/keys/acme.env"
Defensive patterns

Strategy: validation

Validate before calling

if !consent.path.is_absolute() {
    let expanded = expand_tilde(&consent.path)?; // '~' -> $HOME, then check again
    if !expanded.is_absolute() { return Err(anyhow!("consent path must be absolute")); }
}

Type guard

fn is_absolute_path(p: &Path) -> bool { p.is_absolute() }

Try / catch

match consent.validate_read_scope(provider, source, &resolved) {
    Ok(()) => read_external_credential(&resolved),
    Err(e) if e.to_string().contains("must be absolute") => {
        reconsent_with_expanded_path(provider, source, &resolved).await
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: A consent record whose `path` field is relative (e.g. "keys/acme.env" or "~/keys/acme.env" before expansion) is validated for use; Path::is_absolute() is false and the bail fires.

Common situations: Users entering '~/' paths that were never expanded; relative paths working from one cwd in scripts but stored as-is; config copied between machines with home-relative shortcuts.

Related errors


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