Hmbown/CodeWhale · error · anyhow::Error
xAI OAuth path must be a regular file
Error message
xAI OAuth path must be a regular file
What it means
validate_owned_file_handle runs on every opened credential file and on the lifecycle lock: after an O_NOFOLLOW open it verifies the inode is a regular file. Symlinks usually fail earlier with ELOOP at open time; this check catches FIFOs, sockets, devices, or a non-regular file substituted between open and metadata(), so tokens are never read from or written to special files.
Source
Thrown at crates/config/src/xai_credentials.rs:768
)
} != 0
{
return Err(std::io::Error::last_os_error()).context("retiring xAI OAuth file");
}
Ok(())
}
}
#[cfg(unix)]
fn validate_owned_file_handle(file: &File, path: &Path) -> Result<fs::Metadata> {
use std::os::unix::fs::MetadataExt as _;
let metadata = file.metadata().with_context(|| {
format!(
"inspecting Codewhale-owned xAI OAuth file {}",
crate::quote_os_path(path)
)
})?;
anyhow::ensure!(metadata.is_file(), "xAI OAuth path must be a regular file");
anyhow::ensure!(
metadata.uid() == unsafe { libc::geteuid() },
"xAI OAuth file must be owned by the current user"
);
anyhow::ensure!(
metadata.nlink() == 1,
"xAI OAuth file must not have multiple filesystem links"
);
Ok(metadata)
}
#[cfg(windows)]
fn open_owned_credentials_directory(directory: &Path) -> Result<XaiOAuthCredentialStore> {
use std::os::windows::fs::OpenOptionsExt as _;
use windows_sys::Win32::Storage::FileSystem::{
FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT, FILE_GENERIC_READ,
FILE_SHARE_READ, FILE_SHARE_WRITE, WRITE_DAC, WRITE_OWNER,
};View on GitHub (pinned to 8880682c63)
Solutions
- Inspect the entry: ls -l "$CODEWHALE_HOME/credentials" and look for type markers p, s, c, or b
- Remove the offending file: rm "$CODEWHALE_HOME/credentials/<name>", then re-run codewhale auth xai-device
- Find and stop whatever creates non-regular files there
Example fix
# before ls -l "$HOME/.codewhale/credentials" # prw-r--r-- 1 me me 0 xai-auth.json (FIFO) # after rm "$HOME/.codewhale/credentials/xai-auth.json" codewhale auth xai-device
Defensive patterns
Strategy: validation
Validate before calling
#[cfg(unix)]
fn is_plain_file(p: &std::path::Path) -> std::io::Result<bool> {
let ft = std::fs::symlink_metadata(p)?.file_type();
Ok(!ft.is_symlink() && ft.is_file())
} Type guard
#[cfg(unix)]
fn credential_file_is_regular(dir: &std::path::Path, name: &str) -> bool {
std::fs::symlink_metadata(dir.join(name))
.map(|m| !m.file_type().is_symlink() && m.is_file())
.unwrap_or(false)
} Prevention
- Never symlink credential files; move them instead
- Keep the credentials directory out of dotfile managers
- Audit the directory for non-regular entries when logins fail unexpectedly
When it happens
Trigger: xai-auth.json, a generation file, or .xai-oauth.lock inside $CODEWHALE_HOME/credentials is a FIFO, unix socket, or device file; or the path is swapped for a non-regular file between the openat and the metadata call.
Common situations: Misconfigured dotfile tooling or pranks creating special files in the credentials directory; symlink-attack leftovers (these usually surface as the ELOOP open error instead); stale test fixtures.
Related errors
- Codewhale credentials path must be a directory
- Codewhale credentials directory must be owned by the current
- xAI OAuth file must not have multiple filesystem links
- invalid Codewhale-owned xAI OAuth basename
- xAI OAuth private basename must be one UTF-8 path component
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/e88d24a1feb5495a.
Report an issue: GitHub.