Hmbown/CodeWhale · error

could not inspect workspace .env link count

Error message

could not inspect workspace .env link count: {error}

What it means

On Windows, hard-link/symlink detection for the workspace `.env` uses `GetFileInformationByHandle` to read `nNumberOfLinks`. If the Win32 call fails, the error is wrapped with this message, because the loader must prove the file is unique before trusting its contents.

Solutions

  1. Move the workspace `.env` onto a local NTFS volume.
  2. Check the `{error}` suffix (Win32 error code) for the failing subsystem (AV, permissions, filesystem).
  3. Ensure the file is a normal regular file, not on a UNC/network share, then retry startup.
Defensive patterns

Strategy: fallback

Try / catch

match load_workspace_dotenv_credentials_from_path(&path) {
    Err(e) if e.to_string().contains("link count") => {
        eprintln!("move .env to local NTFS storage: {e:#}");
    }
    other => other?,
}

Prevention

When it happens

Trigger: The `GetFileInformationByHandle` syscall fails (invalid handle, AV interference, filesystem without link metadata) inside `workspace_dotenv_has_multiple_links` on Windows.

Common situations: The `.env` lives on an unusual filesystem (network drive, WSL mount) where the handle query fails, or security software blocks handle inspection.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/lib.rs:3000

#[cfg(windows)]
fn workspace_dotenv_has_multiple_links(
    file: &std::fs::File,
    _metadata: &std::fs::Metadata,
) -> Result<bool> {
    use std::os::windows::io::AsRawHandle;
    use windows::Win32::Foundation::HANDLE;
    use windows::Win32::Storage::FileSystem::{
        BY_HANDLE_FILE_INFORMATION, GetFileInformationByHandle,
    };

    let mut information = BY_HANDLE_FILE_INFORMATION::default();
    // SAFETY: `file` owns a live kernel handle for the already-open `.env`;
    // `information` remains writable for the duration of this synchronous
    // call. No path lookup or re-open occurs here.
    unsafe {
        GetFileInformationByHandle(HANDLE(file.as_raw_handle()), &mut information)
            .map_err(|error| anyhow!("could not inspect workspace .env link count: {error}"))?;
    }
    Ok(information.nNumberOfLinks > 1)
}

#[cfg(not(any(unix, windows)))]
fn workspace_dotenv_has_multiple_links(
    _file: &std::fs::File,
    _metadata: &std::fs::Metadata,
) -> Result<bool> {
    Ok(false)
}

#[cfg(unix)]
fn open_workspace_dotenv_without_following_links(path: &Path) -> Result<std::fs::File> {
    use std::os::unix::fs::OpenOptionsExt;

    std::fs::OpenOptions::new()
        .read(true)

View on GitHub (pinned to 73e0f67d83)