astrid-runtime/astrid · error
private path is redirected: {}
Error message
private path is redirected: {} What it means
verify_no_redirects_unix refuses to operate on a path whose final component is a symbolic link, since a symlink could redirect security-sensitive private data outside the intended owner-only location. It fails with io::ErrorKind::InvalidData and the offending path in the message.
Source
Thrown at crates/astrid-core/src/platform_fs.rs:425
#[cfg(unix)]
{
verify_no_redirects_unix(path)
}
#[cfg(not(any(unix, windows)))]
{
let _ = path;
Ok(())
}
}
#[cfg(unix)]
fn verify_no_redirects_unix(path: &Path) -> io::Result<()> {
use nix::fcntl::{OFlag, openat};
use nix::sys::stat::Mode;
match std::fs::symlink_metadata(path) {
Ok(metadata) if metadata.file_type().is_symlink() => Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("private path is redirected: {}", path.display()),
)),
Ok(metadata) if metadata.is_dir() => open_directory_no_follow_unix(path).map(drop),
Ok(_) => {
let parent = path.parent().ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
format!("private path has no parent: {}", path.display()),
)
})?;
let name = path.file_name().ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
format!("private path has no file name: {}", path.display()),
)
})?;
let directory = open_directory_no_follow_unix(parent)?;View on GitHub (pinned to affd8760f4)
Solutions
- Remove the symlink and replace it with a real directory/file (e.g. rsync -L or cp -rL to materialize the target).
- Point your configuration at the real location instead of a symlinked path.
- Re-run ensure_private_directory to rebuild the private path as a real owner-only directory.
Example fix
// before (shell) ln -s /mnt/data/.astrid ~/.astrid // after (shell) rm ~/.astrid && cp -rL /mnt/data/.astrid ~/.astrid && chmod 700 ~/.astrid
Defensive patterns
Strategy: validation
Validate before calling
let meta = std::fs::symlink_metadata(&path)?;
if meta.file_type().is_symlink() {
return Err(format!("{} is a symlink; remove it before use", path.display()));
} Type guard
fn is_no_symlink(p: &std::path::Path) -> bool {
std::fs::symlink_metadata(p).map(|m| !m.file_type().is_symlink()).unwrap_or(false)
} Try / catch
if let Err(e) = verify_no_redirects(&path) {
if e.kind() == io::ErrorKind::InvalidData {
eprintln!("remove the symlink and materialize the real data: {e}");
}
return Err(e);
} Prevention
- Never symlink ~/.astrid or its children (dotfile managers: use real dirs or bind mounts)
- After restore/backup, verify no symlinks were introduced into the private tree
- Copy symlink targets (cp -rL) rather than preserving links
When it happens
Trigger: Calling verify_no_redirects (Unix) with a path whose symlink_metadata reports a symlink file type — e.g. ~/.astrid or a child replaced by a symlink to elsewhere.
Common situations: Backup/restore tools that recreated state as symlinks; dotfile managers (stow, chezmoi) symlinking ~/.astrid into a repo; an attacker-planted symlink in a shared directory.
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
- legacy state source is redirected: {}
- legacy state source contains a redirect: {}
- legacy principal home root is not a regular directory: {}
- legacy principal profile is not a regular file: {}
- principal-store capability entry is redirected or not a dire
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/b84ab5fc53c107ea.
Report an issue: GitHub.