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
- cd into an existing directory (or restart the terminal) and retry
- Pass an absolute credential path so the cwd is never consulted
- 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
- Pass absolute credential paths from wrapper scripts and CI jobs
- Ensure the launch directory outlives the command (never rm -rf the cwd of a running job)
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
- failed to enter ACP session cwd {}: {err}
- search root does not exist: {}
- path has no parent
- parallel(): expected an array of thunks
- Release asset directory must be flat; found: ${nonFiles.map(
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/86ca068711b1efc0.
Report an issue: GitHub.