astrid-runtime/astrid · error
private file has no parent
Error message
private file has no parent: {} What it means
open_file_no_follow_unix needs both a parent directory and a final file name to open the file relative to its parent via openat (for symlink protection). It throws this when path.parent() returns None, which happens for bare-root paths like "/" that cannot name a file.
Solutions
- Pass the full path to the file including its parent directory, not "/" or a bare root.
- Check the configured value; assign the concrete file name (e.g. /home/me/.astrid/credentials).
- Guard caller code to reject paths without a parent before invoking the API.
- If the value comes from user input or env, validate it names a file before use.
Example fix
// before
restrict_private_file(Path::new("/"))?;
// after
restrict_private_file(&Path::new("/home/me/.astrid").join("credentials"))?; Defensive patterns
Strategy: validation
Validate before calling
fn has_parent(path: &std::path::Path) -> bool { path.parent().is_some() } Type guard
fn is_file_path_with_parent(path: &std::path::Path) -> bool {
path.parent().is_some() && path.file_name().is_some()
} Try / catch
assert!(path.parent().is_some(), "private path must include a parent: {}", path.display());
restrict_private_file(path)?; Prevention
- Never pass "/" or empty paths as file arguments
- Validate configured file paths at startup
- Build paths as parent.join(file_name)
When it happens
Trigger: Calling restrict_private_file or validate_private_file with a Path that has no parent component, such as "/" or an empty/normalized root path.
Common situations: A config variable that should hold a file path accidentally holds a mount root or "/"; path-joining code that stripped all components; programmatic construction passing Path::new("").
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- private atomic file has no parent
- private file has no name
- Astrid volume is not a regular file
- cannot resolve install directory for
- capsule source is neither a directory nor a regular file
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/7418398588a6c339.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-core/src/platform_fs.rs:636
}
}
#[cfg(target_os = "macos")]
fn absolute_command_path(path: &Path) -> io::Result<PathBuf> {
if path.is_absolute() {
Ok(path.to_path_buf())
} else {
Ok(std::env::current_dir()?.join(path))
}
}
#[cfg(unix)]
fn open_file_no_follow_unix(path: &Path) -> io::Result<std::fs::File> {
use nix::fcntl::{OFlag, openat};
use nix::sys::stat::Mode;
let parent = path.parent().ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
format!("private file has no parent: {}", path.display()),
)
})?;
let name = path.file_name().ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
format!("private file has no name: {}", path.display()),
)
})?;
let directory = open_directory_no_follow_unix(parent)?;
let flags = OFlag::O_RDONLY | OFlag::O_NOFOLLOW | OFlag::O_CLOEXEC;
openat(&directory, name, flags, Mode::from_bits_truncate(0o600))
.map(std::fs::File::from)
.map_err(nix_io_error)
}
#[cfg(unix)]View on GitHub (pinned to affd8760f4)