Hmbown/CodeWhale · error · anyhow::Error
xAI OAuth credentials directory must be absolute
Error message
xAI OAuth credentials directory must be absolute
What it means
The unix open_owned_credentials_directory requires an absolute directory because it walks every component with openat(2) starting from '/'. The public path (xai_oauth_credentials_dir -> lexical_absolute_path) always absolutizes first, so this fires only when the opener is called directly with a relative path (in-crate tests or refactors that bypass XaiOAuthCredentialStore::open).
Source
Thrown at crates/config/src/xai_credentials.rs:454
}
fn validate_private_basename(name: &str) -> Result<()> {
let path = Path::new(name);
anyhow::ensure!(
path.components().count() == 1
&& matches!(path.components().next(), Some(Component::Normal(_)))
&& path.file_name().and_then(|value| value.to_str()) == Some(name),
"xAI OAuth private basename must be one UTF-8 path component"
);
Ok(())
}
#[cfg(unix)]
fn open_owned_credentials_directory(directory: &Path) -> Result<XaiOAuthCredentialStore> {
use std::os::fd::FromRawFd as _;
use std::os::unix::fs::{MetadataExt as _, PermissionsExt as _};
anyhow::ensure!(
directory.is_absolute(),
"xAI OAuth credentials directory must be absolute"
);
// SAFETY: the literal root path contains no interior NUL and the returned
// descriptor is immediately owned by `File`.
let root_fd = unsafe {
libc::open(
c"/".as_ptr(),
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
if root_fd < 0 {
return Err(std::io::Error::last_os_error()).context("opening filesystem root");
}
// SAFETY: `root_fd` is a newly owned descriptor on the success path above.
let mut current = unsafe { File::from_raw_fd(root_fd) };
for component in directory.components() {
let Component::Normal(name) = component else {View on GitHub (pinned to 8880682c63)
Solutions
- Join the path against std::env::current_dir() or codewhale_config::codewhale_home() before opening
- Use the public entry points (XaiOAuthCredentialStore::open / with_xai_oauth_lifecycle_lock), which absolutize for you
Example fix
// before
open_owned_credentials_directory(Path::new(".codewhale/credentials"))?;
// after
let dir = codewhale_config::codewhale_home()?.join("credentials");
assert!(dir.is_absolute());
open_owned_credentials_directory(&dir)?; Defensive patterns
Strategy: validation
Validate before calling
anyhow::ensure!(
dir.is_absolute(),
"credentials directory must be absolute, got {}",
dir.display()
); Prevention
- Build store paths only through codewhale_home().join("credentials")
- In tests, canonicalize tempdirs before constructing stores
- Never pass cwd-relative paths to directory-pinning helpers
When it happens
Trigger: Direct calls such as open_owned_credentials_directory(Path::new("credentials")) from unit tests or new code; a refactor that skips lexical_absolute_path when computing the directory.
Common situations: Crate-internal tests constructing stores from relative tempdir paths; refactoring that calls the opener directly instead of through the public open().
Related errors
- invalid Codewhale-owned xAI OAuth basename
- xAI OAuth private basename must be one UTF-8 path component
- Codewhale credentials path must be a directory
- Codewhale credentials directory must be owned by the current
- refusing to replace an existing xAI OAuth retirement path
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/d8e138b941e75f6b.
Report an issue: GitHub.