BigPizzaV3/CodexPlusPlus · error

File is a reparse point

Error message

File is a reparse point

What it means

read_regular opens the target file itself with OPEN_REPARSE_POINT so it receives the reparse-point metadata rather than following the link, then rejects the file if FILE_ATTRIBUTE_REPARSE_POINT (0x400) is set. This library only reads ordinary regular files of the browser runtime it patches; reading through a symlink/junction would defeat the integrity guarantees (hash pinning) of the adaptation. Any linked file is treated as unsupported.

Solutions

  1. Replace the linked file with a real copy: copy the target's contents to a fresh regular file at the path (del the link, then copy).
  2. Reinstall or repair the Codex runtime so all files under the runtime root are plain regular files.
  3. Verify with `fsutil reparsepoint query <file>` or `dir /AL` which files are reparse points, and fix each one before retrying.
  4. Avoid tools that materialize the runtime as symlinks (e.g. package-manager linking) when staging this directory.

Example fix

// before: file is a symlink to a shared copy
browser-service.mjs -> D:\shared\browser-service.mjs
// after: materialize a real file
cp --remove-destination D:\shared\browser-service.mjs browser-service.mjs
Defensive patterns

Strategy: validation

Validate before calling

fn assert_regular_file(path: &Path) -> std::io::Result<()> {
    let meta = std::fs::symlink_metadata(path)?;
    if meta.file_type().is_symlink() {
        return Err(std::io::Error::new(
            std::io::ErrorKind::InvalidInput,
            format!("{} is a symlink", path.display()),
        ));
    }
    #[cfg(windows)]
    {
        use std::os::windows::fs::MetadataExt;
        if meta.file_attributes() & 0x400 != 0 {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                format!("{} is a reparse point", path.display()),
            ));
        }
    }
    if !meta.is_file() {
        return Err(std::io::Error::new(
            std::io::ErrorKind::InvalidInput,
            format!("{} is not a regular file", path.display()),
        ));
    }
    Ok(())
}

Type guard

fn is_plain_file(p: &Path) -> bool {
    match std::fs::symlink_metadata(p) {
        Ok(m) => m.is_file() && !m.file_type().is_symlink(),
        Err(_) => false,
    }
}

Try / catch

match result {
    Err(e) if e.to_string().contains("reparse point") => {
        eprintln!("Replace the linked file with a real copy before retrying: {e}");
    }
    Err(e) => return Err(e.into()),
    Ok(bytes) => process(bytes),
}

Prevention

When it happens

Trigger: Any read path (discover, prepare, recovery_material, restore_all, read_status, verify_restored_state) where the target file — e.g. bin/node_repl.exe, bin/node.exe, manifest.json, or browser-service.mjs — is a symlink, hardlink-with-reparse-tag, or other NTFS reparse point.

Common situations: Developer copies the runtime with a tool that created symlinks; the installation was cloned from another machine using symlink-capable software; pnpm/npm-style linking habits applied to runtime files; version upgrades replaced a file with a link to a shared copy.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19). Data as JSON: /api/errors/cb4727ac5b59f984. Report an issue: GitHub.

Appendix: source

Thrown at crates/codex-plus-core/src/native_browser.rs:180

    }
    Ok(guards)
}

fn read_regular(path: &Path, limit: u64) -> Result<Vec<u8>> {
    let _guards = pin_parents(path)?;
    let mut options = OpenOptions::new();
    options.read(true);
    #[cfg(windows)]
    {
        use std::os::windows::fs::OpenOptionsExt;
        options.share_mode(0x1).custom_flags(0x00200000);
    }
    let file = options.open(path)?;
    let meta = file.metadata()?;
    #[cfg(windows)]
    {
        use std::os::windows::fs::MetadataExt;
        ensure!(
            meta.file_attributes() & 0x400 == 0,
            "File is a reparse point"
        );
    }
    ensure!(
        meta.is_file() && meta.len() <= limit,
        "Unexpected file type or size"
    );
    let mut bytes = Vec::new();
    file.take(limit + 1).read_to_end(&mut bytes)?;
    ensure!(
        bytes.len() as u64 <= limit,
        "File grew beyond the size limit"
    );
    Ok(bytes)
}

fn write_new(path: &Path, bytes: &[u8]) -> Result<File> {

View on GitHub (pinned to b1ed92e5e4)