Hmbown/CodeWhale · error

reviewed plugin cwd is a reparse point or non-directory

Error message

reviewed plugin cwd is a reparse point or non-directory

What it means

On Windows, bind_cwd opens the plugin's configured working directory with FILE_SHARE_READ only plus BACKUP_SEMANTICS|OPEN_REPARSE_POINT, then requires the handle metadata to be a directory without FILE_ATTRIBUTE_REPARSE_POINT (0x400) (crates/tui/src/mcp.rs:956-968). This error fires when cwd is a symlink/junction/mount point or not a directory at all: the launcher refuses to pin trust to a path that can be redirected.

Source

Thrown at crates/tui/src/mcp.rs:967

                .open(cwd)
                .context("open reviewed plugin cwd without following links")?;
            self.cwd_fd = Some(file);
            self.cwd = None;
        }
        #[cfg(windows)]
        {
            use std::os::windows::fs::{MetadataExt as _, OpenOptionsExt as _};
            let file = fs::OpenOptions::new()
                .read(true)
                .share_mode(0x0000_0001) // FILE_SHARE_READ only
                .custom_flags(0x0220_0000) // BACKUP_SEMANTICS | OPEN_REPARSE_POINT
                .open(cwd)
                .context("open reviewed plugin cwd without write/delete sharing")?;
            let metadata = file
                .metadata()
                .context("inspect reviewed plugin cwd handle")?;
            if !metadata.is_dir() || metadata.file_attributes() & 0x0000_0400 != 0 {
                anyhow::bail!("reviewed plugin cwd is a reparse point or non-directory");
            }
            self.opened_files.push(file);
        }
        Ok(())
    }
}

#[cfg(unix)]
fn open_reviewed_launch_file(path: &Path) -> Result<fs::File> {
    crate::plugins::manifest::open_bundle_file(path)
        .context("open reviewed launch file without following links")
}

#[cfg(windows)]
fn open_reviewed_launch_file(path: &Path) -> Result<fs::File> {
    crate::plugins::manifest::open_bundle_file(path)
        .context("open reviewed launch file without links, hard links, or write/delete sharing")
}

View on GitHub (pinned to 8880682c63)

Solutions

  1. Point cwd at a plain real directory: locate the reparse point with `dir /AL` or `fsutil reparsepoint query <dir>` and replace the junction path with the physical target path.
  2. If a junction is required by your environment, materialize a real directory at the manifest's cwd and move the contents there.
  3. After editing the manifest, run /plugin reload and re-run /plugin trust so the new paths enter the receipt.
  4. Verify with PowerShell: (Get-Item <dir>).LinkType must be empty and Attributes must include Directory but not ReparsePoint.

Example fix

# before: cwd is a junction -> reviewed plugin cwd is a reparse point or non-directory
[mcp.server]
cwd = "C:\Users\me\Dropbox\plugins\demo"
# after: physical directory, no reparse point
[mcp.server]
cwd = "D:\work\plugins\demo"
Defensive patterns

Strategy: validation

Validate before calling

#[cfg(windows)]
fn cwd_is_plain_dir(cwd: &std::path::Path) -> bool {
    use std::os::windows::fs::MetadataExt;
    match std::fs::symlink_metadata(cwd) {
        Ok(md) => md.is_dir() && md.file_attributes() & 0x0000_0400 == 0,
        Err(_) => false,
    }
}

Prevention

When it happens

Trigger: plugin.toml cwd resolves to an NTFS junction or directory symlink, or cwd names a file/leftover path instead of a real directory.

Common situations: Home-directory junctions created by Dropbox/OneDrive redirection; manifests ported from macOS/Linux setups that used symlinks; WSL/Windows path mixups where cwd points at a file.

Related errors


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