Hmbown/CodeWhale · error · std::io::Error

plugin directory is a reparse point or non-directory

Error message

plugin directory is a reparse point or non-directory

What it means

Hardening guard in open_bundle_directory (Windows): the opened plugin directory path has the reparse-point attribute or is not actually a directory, so it is rejected. Plugin directories must be real directories to prevent junction/symlink redirection.

Source

Thrown at crates/tui/src/plugins/manifest.rs:1572

#[cfg(all(not(unix), not(windows)))]
pub(crate) fn open_bundle_file(path: &Path) -> std::io::Result<fs::File> {
    fs::File::open(path)
}

#[cfg(windows)]
fn open_bundle_directory(path: &Path) -> std::io::Result<fs::File> {
    use std::os::windows::fs::OpenOptionsExt as _;

    const FILE_ATTRIBUTE_REPARSE_POINT: u32 = 0x0000_0400;
    let file = fs::OpenOptions::new()
        .read(true)
        .share_mode(0x0000_0001)
        .custom_flags(0x0220_0000) // BACKUP_SEMANTICS | OPEN_REPARSE_POINT
        .open(path)?;
    let metadata = file.metadata()?;
    let identity = windows_file_identity(&file)?;
    if !metadata.is_dir() || identity.attributes & FILE_ATTRIBUTE_REPARSE_POINT != 0 {
        return Err(std::io::Error::new(
            std::io::ErrorKind::InvalidData,
            "plugin directory is a reparse point or non-directory",
        ));
    }
    Ok(file)
}

/// Reopen a reviewed path only to compare its current handle identity with a
/// retained authority handle. Desired access is zero and sharing is permissive
/// because the retained handle remains responsible for denying writes and
/// replacement throughout the comparison.
#[cfg(windows)]
pub(crate) fn open_bundle_identity_probe(
    path: &Path,
    expect_directory: bool,
) -> std::io::Result<fs::File> {
    use std::os::windows::fs::OpenOptionsExt as _;

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Remove the junction/symlink and install the plugin as a real directory.
  2. Re-install the plugin through the normal plugin flow so a genuine directory is created.
  3. Check the plugin root for virtualization or redirection layers.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at crates/tui/src/plugins/manifest.rs:1572 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/a88232acd2204ecd. Report an issue: GitHub.