Hmbown/CodeWhale · error · anyhow::Error

resolving external credential path: {err}

Error message

resolving external credential path: {err}

What it means

resolve_external_credential_path turns a user-selected credential path into an absolute logical path without touching the filesystem (consent binds to the exact logical path). For a relative path it must join the current working directory; this error wraps the OS failure of std::env::current_dir().

Source

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

            | '\u{200f}'
            | '\u{2028}'
            | '\u{2029}'
            | '\u{202a}'..='\u{202e}'
            | '\u{2066}'..='\u{2069}'
    )
}

/// Resolve a user-selected path without touching the filesystem.
///
/// Consent is bound to the exact logical path, so this intentionally avoids
/// canonicalization (which would stat the candidate before consent exists).
pub fn resolve_external_credential_path(path: impl AsRef<Path>) -> Result<PathBuf> {
    let path = path.as_ref();
    let absolute = if path.is_absolute() {
        path.to_path_buf()
    } else {
        std::env::current_dir()
            .map_err(|err| anyhow::anyhow!("resolving external credential path: {err}"))?
            .join(path)
    };

    // Normalize only lexical `.` / `..` components. Canonicalization would
    // inspect a credential path before consent exists and would also silently
    // bless a symlink target. The secure reader rejects symlink/reparse-point
    // components when the granted capability is actually consumed.
    let mut normalized = PathBuf::new();
    for component in absolute.components() {
        match component {
            Component::Prefix(prefix) => normalized.push(prefix.as_os_str()),
            Component::RootDir => normalized.push(component.as_os_str()),
            Component::CurDir => {}
            Component::ParentDir => {
                if !normalized.pop() {
                    bail!(
                        "external credential path escapes its absolute root: {}",
                        quote_os_path(&absolute)

View on GitHub (pinned to 8880682c63)

Solutions

  1. cd into an existing directory (or restart the terminal) and retry
  2. Pass an absolute credential path so the cwd is never consulted
  3. If a wrapper script chdir's into a temp dir, make sure that dir still exists when the command runs

Example fix

# before (shell sitting in a deleted directory)
$ codewhale credentials add ./key.json   # resolving external credential path: No such file or directory

# after
$ cd ~ && codewhale credentials add ~/keys/key.json
Defensive patterns

Strategy: validation

Validate before calling

// Absolutize without relying on a live cwd, or verify cwd first:
fn safe_absolute(p: &std::path::Path) -> std::io::Result<std::path::PathBuf> {
    if p.is_absolute() {
        Ok(p.to_path_buf())
    } else {
        std::env::current_dir().map(|d| d.join(p))
    }
}

Try / catch

On Err, tell the user the working directory is gone and re-prompt with an absolute path; a retry only helps after the cwd exists again, so do not loop on it.

Prevention

When it happens

Trigger: Passing a relative external-credential path while the process working directory was deleted (Linux getcwd fails with ENOENT) or made unreadable (EACCES), so the OS cannot report it.

Common situations: A shell sitting in a directory that was rm -rf'ed; CI running from a workspace deleted mid-job; containers whose mount was removed before the command ran.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/86ca068711b1efc0. Report an issue: GitHub.