astrid-runtime/astrid · error
workspace tree contains a redirected or special entry: {}
Error message
workspace tree contains a redirected or special entry: {} What it means
verify_tree walks the workspace tree and rejects any entry that is a symlink, is neither a regular file nor a directory, or whose canonicalized path differs from its walked path. This InvalidInput guards against symlink-based escapes and special files (FIFOs, devices, sockets) appearing inside the workspace, which could redirect reads/writes outside the trusted root.
Source
Thrown at crates/astrid-core/src/workspace_security.rs:151
/// Returns an error if the root is unsafe, any descendant is a symlink,
/// reparse redirect, or special file, or the tree changes while walking.
pub fn verify_tree(&self, relative: impl AsRef<Path>) -> io::Result<PathBuf> {
let relative = relative.as_ref();
let root = self.resolve_directory(relative)?;
if !root.exists() {
return Ok(root);
}
let mut pending = vec![root.clone()];
while let Some(dir) = pending.pop() {
for entry in std::fs::read_dir(&dir)? {
let entry = entry?;
let path = entry.path();
let metadata = std::fs::symlink_metadata(&path)?;
if metadata.file_type().is_symlink()
|| (!metadata.is_dir() && !metadata.is_file())
|| std::fs::canonicalize(&path)? != path
{
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"workspace tree contains a redirected or special entry: {}",
path.display()
),
));
}
if metadata.is_dir() {
pending.push(path);
}
}
}
self.resolve_directory(relative)?;
Ok(root)
}
fn resolve_descendant(&self, relative: &Path, kind: DescendantKind) -> io::Result<PathBuf> {
self.verify()?;View on GitHub (pinned to affd8760f4)
Solutions
- Remove or replace symlinks inside the workspace tree with real files/directories or copies.
- Delete or relocate special files (FIFOs, sockets, device nodes) out of the workspace.
- Find the offending entry named in the error and check why it canonicalizes elsewhere (readlink/find -type l).
- Configure tools that create links (package managers, build scripts) to use copies or hardlink-free modes within the workspace.
Example fix
// before: workspace contains a symlink // mylib -> /opt/shared/mylib // after git rm mylib cp -rL /opt/shared/mylib mylib # materialize a real copy
Defensive patterns
Strategy: validation
Validate before calling
fn tree_clean(dir: &Path) -> std::io::Result<()> {
for entry in std::fs::read_dir(dir)? {
let p = entry?.path();
let m = std::fs::symlink_metadata(&p)?;
if m.file_type().is_symlink() || (!m.is_dir() && !m.is_file()) {
return Err(io::Error::new(io::ErrorKind::InvalidInput, "bad entry"));
}
if m.is_dir() { tree_clean(&p)?; }
}
Ok(())
} Prevention
- Never commit symlinks or special files into workspace trees
- Configure package managers/build tools to copy instead of symlink inside the workspace
- Run find <root> -type l periodically to detect stray links
When it happens
Trigger: Calling verify (or an operation that validates the tree) when the workspace contains a symlink, a FIFO/socket/device, or any entry whose canonical path diverges (e.g. a hardlinked bind or a path containing '..' resolved through a symlinked parent).
Common situations: Checkouts that include symlinked dependencies (node_modules links, vendored symlinks); build systems creating FIFOs; a colleague or tool commiting symlinks pointing outside the repo; mounts appearing inside the tree during validation.
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
- leftover capsule authority receipt is not a regular file: {}
- legacy capsule authority root is not a regular directory: {}
- legacy capsule authority root contains a non-regular entry:
- legacy capsule authority root is not a regular directory: {}
- symlink {} resolves outside the capsule source root ({}); re
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/58adba9748d252d3.
Report an issue: GitHub.