astrid-runtime/astrid · error
legacy audit tree is redirected or not a directory
Error message
legacy audit tree is redirected or not a directory: {path} What it means
validate_audit_tree recursively re-checks every node of the audit tree before and after the retirement rename. Any node that is a symlink or not a directory means part of the tree could redirect writes outside the validated device, so the whole tree is rejected with InvalidData.
Solutions
- Find the offending node (walk the tree with `find <path> -type l -o ! -type d`) and replace the symlink/file with a real directory
- Materialize symlinked subdirectories back into the tree (mv the target content in place)
- Repair or recreate the audit tree from logs if it is structurally corrupted
Example fix
// before audit/shard-3 -> /mnt/spare/shard-3 (symlink inside tree) // after rm audit/shard-3 && mv /mnt/spare/shard-3 audit/shard-3
Defensive patterns
Strategy: validation
Validate before calling
fn tree_has_no_symlinks(root: &std::path::Path) -> std::io::Result<bool> {
for entry in walkdir_like(root)? {
let m = std::fs::symlink_metadata(&entry)?;
if m.file_type().is_symlink() { return Ok(false); }
}
Ok(true)
} Type guard
fn is_real_directory(p: &std::path::Path) -> bool {
matches!(std::fs::symlink_metadata(p), Ok(m) if m.is_dir() && !m.file_type().is_symlink())
} Try / catch
if let Err(e) = run_migration() {
if e.kind() == std::io::ErrorKind::InvalidData
&& e.to_string().contains("redirected or not a directory") {
// locate offending node from the message path, materialize it, retry
} else { return Err(e); }
} Prevention
- Run `find <audit_root> -type l` as a pre-flight check before upgrading
- Ban symlinks inside the audit tree by policy
- After restoring backups, verify no links were substituted for directories
When it happens
Trigger: Retiring the legacy audit tree when any subdirectory inside it is a symlink, or when a file exists where a directory is expected in the audit hierarchy.
Common situations: Admins symlinking a large audit subdirectory to another disk; corrupted/partial audit trees after crashes; backup-restore tools replacing directories with links.
Related errors
- legacy audit source is not a regular directory
- capsule path escaped source root
- directory symlink not allowed in capsule source tree…
- inspect projected file
- legacy audit tree crosses a filesystem or mount boundary
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/b3da9caa20ac300f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-kernel/src/lib.rs:4322
}
},
Err(error) => return Err(error),
}
Ok(())
}
#[cfg(unix)]
fn audit_tree_device(metadata: &std::fs::Metadata) -> u64 {
use std::os::unix::fs::MetadataExt as _;
metadata.dev()
}
#[cfg(unix)]
fn validate_audit_tree(path: &Path, root_device: u64) -> std::io::Result<()> {
let metadata = std::fs::symlink_metadata(path)?;
if metadata.file_type().is_symlink() || !metadata.is_dir() {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(
"legacy audit tree is redirected or not a directory: {}",
path.display()
),
));
}
if audit_tree_device(&metadata) != root_device || audit_mountpoint(path)? {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(
"legacy audit tree crosses a filesystem or mount boundary: {}",
path.display()
),
));
}
astrid_core::platform_fs::verify_no_redirects(path)?;
for entry in std::fs::read_dir(path)? {View on GitHub (pinned to affd8760f4)