astrid-runtime/astrid · error
private path is not a directory
Error message
private path is not a directory
What it means
On targets that are neither Unix nor Windows, validate_private_directory falls back to a weak check: it only verifies the path is a directory via symlink_metadata. This error means the given path exists but is not a directory (e.g. it is a file or symlink to a file), so the private-directory contract cannot be validated.
Solutions
- Check the path and replace the file with the intended directory, or point configuration at the correct directory path.
- Create the directory first (ensure_private_directory / create_dir_all) before validating.
- If you only need existence+type checks on exotic targets, guard the call with std::path::Path::is_dir() first.
Example fix
// before
validate_private_directory(&cfg.private_dir)?;
// after
if !cfg.private_dir.is_dir() {
return Err(format!("{} is not a directory; check your config", cfg.private_dir.display()).into());
}
validate_private_directory(&cfg.private_dir)?; Defensive patterns
Strategy: validation
Validate before calling
if !path.is_dir() {
return Err(format!("private path {} is not a directory", path.display()));
} Type guard
fn is_real_directory(p: &std::path::Path) -> bool {
std::fs::symlink_metadata(p).map(|m| m.is_dir()).unwrap_or(false)
} Try / catch
match validate_private_directory(&path) {
Err(e) if e.to_string().contains("not a directory") => {
std::fs::create_dir_all(&path)?;
validate_private_directory(&path)?;
}
other => other?,
} Prevention
- Verify configured paths point at directories before validating
- Create directories with ensure_private_directory instead of pointing config at ad-hoc paths
- Check for stray files left where directories are expected after failed installs
When it happens
Trigger: Calling validate_private_directory(path) on a non-unix/non-windows target where `path` resolves to a regular file, device, or other non-directory entry.
Common situations: Config pointing at a file instead of a directory; a stale file left where a data directory should be; porting the library to a platform (e.g. wasm) with the wrong path configured.
Related errors
- groups path has no parent directory
- legacy audit source has no parent
- capsule materialization target is redirected or not a…
- failed to resolve workspace root
- inspect capsule materialization
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/161aca13e58275a3.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-core/src/platform_fs.rs:199
///
/// Returns an error when the directory is missing, redirected, not owned by the
/// current user, or does not satisfy the platform private-access policy.
pub fn validate_private_directory(path: &Path) -> io::Result<()> {
#[cfg(unix)]
{
validate_private_directory_unix(path)
}
#[cfg(windows)]
{
windows::ensure_private_directory(path)
}
#[cfg(not(any(unix, windows)))]
{
let metadata = std::fs::symlink_metadata(path)?;
if !metadata.is_dir() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"private path is not a directory",
));
}
Ok(())
}
}
/// Rename one filesystem entry with the strongest supported namespace
/// durability for the host platform.
///
/// Windows uses `MoveFileExW(MOVEFILE_WRITE_THROUGH)`, which does not return
/// until the move has been flushed. Unix callers must still synchronize the
/// affected parent directories after this atomic rename.
///
/// Windows rejects an existing destination because the write-through move does
/// not request replacement. Other platforms retain `std::fs::rename`
/// replacement semantics. Security-sensitive callers remain responsible forView on GitHub (pinned to affd8760f4)