Hmbown/CodeWhale · error
external credential path must resolve to an absolute path
Error message
external credential path must resolve to an absolute path: {} What it means
Thrown by resolve_external_credential_path when, after lexically normalizing components, the resulting path is not absolute. The contract is that external credential sources must be absolute paths; relative paths are ambiguous because they would resolve against an unpredictable working directory, so the resolver rejects them outright.
Solutions
- Expand `~` and relative segments to a full absolute path before calling (e.g. use dirs::home_dir() or std::env::current_dir().join())
- Store absolute paths in the external credential source configuration
- On Windows include the drive letter (C:\...) in the configured path
- Use the canonicalized path from std::fs::canonicalize before handing it to the resolver
Example fix
// before
resolve_external_credential_path("~/secrets/token.txt")?;
// after
let home = std::env::var("HOME").unwrap();
resolve_external_credential_path(format!("{home}/secrets/token.txt"))?; Defensive patterns
Strategy: validation
Validate before calling
fn ensure_absolute(p: &std::path::Path) -> Option<std::path::PathBuf> {
if p.is_absolute() { Some(p.to_path_buf()) }
else { std::env::current_dir().ok().map(|d| d.join(p)) }
}
// expand '~' via home_dir() before resolving Type guard
fn is_absolute_path(p: &str) -> bool { std::path::Path::new(p).is_absolute() } Prevention
- Store absolute paths (with drive letter on Windows) in configuration
- Expand `~` at config-load time, not at read time
- Prefer fs::canonicalize when recording paths
When it happens
Trigger: Passing a relative path such as "creds/token.txt" or "~/token" (tilde is not expanded by this function) to resolve_external_credential_path; on Windows, a path without a drive/prefix after normalization.
Common situations: Users typing relative paths into config for external credential sources; shell-style `~` paths pasted verbatim into configuration; scripts built from CWD-relative fragments.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Codewhale credentials directory cannot be a volume root
- agent profile path is not a directory
- Codewhale credentials directory must be lexically normalized
- CODEWHALE_HOME / user home is unavailable
- Codewhale-owned xAI OAuth path has the wrong filesystem type
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/c5b8ff6049ef40bf.
Report an issue: GitHub.
Appendix: source
Thrown at crates/config/src/external_credentials.rs:139
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)
);
}
}
Component::Normal(part) => normalized.push(part),
}
}
if !normalized.is_absolute() {
bail!(
"external credential path must resolve to an absolute path: {}",
quote_os_path(&normalized)
);
}
Ok(normalized)
}
/// The side-effect envelope Codewhale may use for an external credential.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ExternalCredentialAccess {
/// Do not inspect or access the external credential store.
#[default]
Disabled,
/// Read the exact selected file without refreshing or rewriting it.
ReadOnly,
/// Permit a documented preservation adapter to refresh and rewrite it.
Managed,View on GitHub (pinned to 73e0f67d83)