Hmbown/CodeWhale · error

Codewhale credentials directory cannot be a volume root

Error message

Codewhale credentials directory cannot be a volume root

What it means

When walking the directory's components to open an owned handle per component, the handle list must be non-empty; an empty list means the path was a volume root (e.g. `C:\` or `/`), which has no per-component handle to secure. Using a volume root as the credential store would give the ownership/DACL guarantees nothing to scope to, so it is refused.

Solutions

  1. Point the store at a real subdirectory (e.g. `/home/user/.codewhale/xai`, not `/` or `C:\` )
  2. Fix the config/env value or the join logic that produced a bare root path
  3. Create the intended credentials subdirectory before opening the store

Example fix

// before
let dir = PathBuf::from("C:\\");
// after
let dir = PathBuf::from("C:\\Users\\me\\.codewhale\\xai");
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_not_volume_root(dir: &std::path::Path) -> Result<(), String> {
    let mut comps = dir.components();
    if comps.next().is_some() && comps.next().is_none() {
        return Err(format!("{} is a volume root; use a subdirectory", dir.display()));
    }
    Ok(())
}

Try / catch

ensure_not_volume_root(&dir)?;
std::fs::create_dir_all(&dir)?;
let store = XaiCredentialStore::open(&dir)?;

Prevention

When it happens

Trigger: Calling open with the path reduced to a root component — `Path::new("/")`, `Path::new("C:\\")`, or a UNC share root like `\\server\share` — after lexical normalization strips CurDir/ParentDir components.

Common situations: A config file or env var set to a drive root or `/`; a path-joining bug that dropped all subdirectories; accidentally passing `home_dir()` that resolved to `/` in a container.

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


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/3783dc3611fc11f3. Report an issue: GitHub.

Appendix: source

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

                    .read(true)
                    .share_mode(FILE_SHARE_READ | FILE_SHARE_WRITE)
                    .custom_flags(FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT);
                let handle = options.open(&current).with_context(|| {
                    format!(
                        "opening Codewhale credentials directory component {}",
                        crate::quote_os_path(&current)
                    )
                })?;
                validate_windows_handle_path(&handle, &current, true)?;
                handles.push(handle);
            }
            Component::CurDir | Component::ParentDir => bail!(
                "Codewhale credentials directory must be lexically normalized: {}",
                crate::quote_os_path(directory)
            ),
        }
    }
    anyhow::ensure!(
        !handles.is_empty(),
        "Codewhale credentials directory cannot be a volume root"
    );
    let mut secure_options = fs::OpenOptions::new();
    secure_options
        .access_mode(FILE_GENERIC_READ | WRITE_DAC | WRITE_OWNER)
        .share_mode(FILE_SHARE_READ | FILE_SHARE_WRITE)
        .custom_flags(FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT);
    let final_directory = secure_options.open(directory).with_context(|| {
        format!(
            "opening Codewhale credentials directory for owner-only security: {}",
            crate::quote_os_path(directory)
        )
    })?;
    validate_windows_handle_path(&final_directory, directory, true)?;
    secure_windows_owner_only_handle(&final_directory, true)
        .context("securing Codewhale credentials directory for the current user")?;
    verify_windows_owner_only_handle(&final_directory)

View on GitHub (pinned to 73e0f67d83)