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
- 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).
- Reinstall or repair the Codex runtime so all files under the runtime root are plain regular files.
- Verify with `fsutil reparsepoint query <file>` or `dir /AL` which files are reparse points, and fix each one before retrying.
- 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
- Copy runtime files with copy semantics, not link semantics (avoid cp -s, pnpm-style linking)
- After cloning/moving an installation, verify no entries are symlinks (`dir /AL` or find -type l)
- Reinstall the runtime from an official installer rather than hand-copying trees between machines
- Check fsutil reparsepoint query on files the library reads
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
- Parent directory is a reparse point
- Dream Skin path must not be a symbolic link
- Monitor lock is a reparse point
- Reparse observation file
- 拒绝删除文件系统根目录:
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)