BigPizzaV3/CodexPlusPlus · error
Linked paths are unsupported
Error message
Linked paths are unsupported
What it means
plain_path rejects any path that contains a symlink at any ancestor level, checked with fs::symlink_metadata. Native browser isolation assumes real on-disk directories; links (including Windows junctions, which report as symlinks here) could redirect writes outside the sandbox, so they are refused with 'Linked paths are unsupported'.
Solutions
- Replace the symlink/junction with a real directory, or move the data and update config to point at the real (link-free) path
- Point the native browser root at a path with no links in any ancestor (e.g. C:\\codex-browser\\...)
- On Windows prefer junction-free relocation via configuration instead of filesystem links
- Detect the condition proactively: walk ancestors and check symlink_metadata before configuring the root
Example fix
// before: runtime root is a junction to D:\caches\browser runtime_root = "C:\\Users\\me\\AppData\\Local\\browser-link" // after: point directly at the real directory runtime_root = "D:\\caches\\browser"
Defensive patterns
Strategy: validation
Validate before calling
fn has_symlink_ancestor(p: &Path) -> bool {
p.ancestors().any(|a| fs::symlink_metadata(a).map(|m| m.file_type().is_symlink()).unwrap_or(false))
} Type guard
fn is_plain_path(p: &Path) -> bool {
p.is_absolute() && !has_symlink_ancestor(p)
} Try / catch
match plain_path(p) {
Err(e) if e.to_string().contains("Linked paths") => {
eprintln!("{} (or a parent) is a symlink/junction; use the real directory", p.display());
}
other => other?,
} Prevention
- Avoid symlinked or junctioned directories for browser roots/caches
- Use configuration-based relocation instead of filesystem links
- Check symlink_metadata along ancestors before configuring roots
When it happens
Trigger: pin_parents, selected_key, discover, prepare, restore_all, or reconcile_contract given a path under a directory that is itself a symlink or junction — e.g. a runtime root that is a link, or any parent directory in the chain.
Common situations: Users symlink ~/.localappdata-like folders to another drive; Windows junctions created to move large browser caches to another volume; dotfile managers symlinking config directories; macOS/Linux symlinked homes.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- 无效的市场主题下载文件名
- Parent traversal is unsupported
- archived lookup task failed
- Backup source database is not an allowed local storage path
- built-in Dream Skin theme cannot be deleted
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/ad3126f4ac20eaad.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/native_browser.rs:113
candidate_sha: String,
modified_secs: u64,
modified_nanos: u32,
}
fn sha(bytes: &[u8]) -> String {
format!("{:x}", Sha256::digest(bytes))
}
fn key_valid(key: &str) -> bool {
key.len() == 16 && key.bytes().all(|b| b.is_ascii_hexdigit())
}
// Reject junctions as well as symlinks, including in parent directories.
fn plain_path(path: &Path) -> Result<()> {
ensure!(path.is_absolute(), "Expected an absolute local path");
for ancestor in path.ancestors() {
if let Ok(meta) = fs::symlink_metadata(ancestor) {
ensure!(
!meta.file_type().is_symlink(),
"Linked paths are unsupported"
);
#[cfg(windows)]
{
use std::os::windows::fs::MetadataExt;
ensure!(
meta.file_attributes() & 0x400 == 0,
"Reparse paths are unsupported"
);
}
}
}
ensure!(
!path
.components()
.any(|c| matches!(c, std::path::Component::ParentDir)),
"Parent traversal is unsupported"View on GitHub (pinned to b1ed92e5e4)