Hmbown/CodeWhale · error

Codewhale-owned xAI OAuth path must not be a reparse point

Error message

Codewhale-owned xAI OAuth path must not be a reparse point

What it means

Every windows handle is opened with FILE_FLAG_OPEN_REPARSE_POINT and then rejected when its attributes include FILE_ATTRIBUTE_REPARSE_POINT. This makes symlinks and junctions fail closed for the credentials leaf, every ancestor component, and every credential file, preserving the lexical Codewhale-owned boundary so an external directory can never impersonate the store.

Source

Thrown at crates/config/src/xai_credentials.rs:1209

    expected: &Path,
    expect_directory: bool,
) -> Result<fs::Metadata> {
    use std::ffi::OsString;
    use std::os::windows::ffi::OsStringExt as _;
    use std::os::windows::fs::MetadataExt as _;
    use std::os::windows::io::AsRawHandle as _;
    use windows_sys::Win32::Storage::FileSystem::{
        FILE_ATTRIBUTE_REPARSE_POINT, FILE_NAME_NORMALIZED, GetFinalPathNameByHandleW,
        VOLUME_NAME_DOS,
    };

    let metadata = file.metadata().with_context(|| {
        format!(
            "inspecting Codewhale-owned path {}",
            crate::quote_os_path(expected)
        )
    })?;
    anyhow::ensure!(
        metadata.file_attributes() & FILE_ATTRIBUTE_REPARSE_POINT == 0,
        "Codewhale-owned xAI OAuth path must not be a reparse point"
    );
    anyhow::ensure!(
        if expect_directory {
            metadata.is_dir()
        } else {
            metadata.is_file()
        },
        "Codewhale-owned xAI OAuth path has the wrong filesystem type"
    );
    let flags = FILE_NAME_NORMALIZED | VOLUME_NAME_DOS;
    let handle = file.as_raw_handle();
    // SAFETY: null output asks only for the required UTF-16 length.
    let needed = unsafe { GetFinalPathNameByHandleW(handle, std::ptr::null_mut(), 0, flags) };
    if needed == 0 {
        return Err(std::io::Error::last_os_error())
            .context("resolving Codewhale-owned xAI OAuth handle path");

View on GitHub (pinned to 8880682c63)

Solutions

  1. Replace the link with a real directory: remove the junction/symlink (rmdir or del on the link only), create a real directory, then re-run codewhale auth xai-device
  2. Point CODEWHALE_HOME at a real local NTFS directory instead of linking to one
  3. Move the actual directory to the expected location rather than linking to it

Example fix

# before (PowerShell)
New-Item -ItemType SymbolicLink -Path "$env:USERPROFILE\.codewhale" -Target "D:\sync\codewhale"

# after
Remove-Item "$env:USERPROFILE\.codewhale"      # removes the link only
New-Item -ItemType Directory -Path "$env:USERPROFILE\.codewhale"
codewhale auth xai-device
Defensive patterns

Strategy: validation

Validate before calling

#[cfg(windows)]
fn no_reparse_ancestry(p: &std::path::Path) -> bool {
    p.ancestors().all(|a| {
        std::fs::symlink_metadata(a)
            .map(|m| !m.file_type().is_symlink())
            .unwrap_or(true)
    })
}

Type guard

#[cfg(windows)]
fn path_is_link_free(p: &std::path::Path) -> bool {
    std::fs::symlink_metadata(p)
        .map(|m| !m.file_type().is_symlink())
        .unwrap_or(true)
}

Prevention

When it happens

Trigger: $CODEWHALE_HOME or any ancestor is a symlink/junction (dotfile managers, relocated profiles); the credentials directory itself is a symlink to another location; cloud-sync placeholder reparse tags also carry the attribute.

Common situations: Users symlinking ~/.codewhale into a synced or shared folder; Windows profile junctions; dev boxes redirecting home with directory links.

Related errors


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