astrid-runtime/astrid · error
legacy audit tree crosses a filesystem or mount boundary
Error message
legacy audit tree crosses a filesystem or mount boundary: {path} What it means
As part of validating the audit tree, each node's st_dev is compared against the root device and each path is checked for being a mountpoint. A subtree on a different filesystem (or a mounted subdirectory) would break the same-device rename and durability assumptions, so validate_audit_tree rejects it with InvalidData.
Solutions
- Unmount any filesystems mounted inside the audit tree (see /proc/mounts or `mountpoint <path>`) and re-run
- Move the data from the cross-device subtree onto the same filesystem and remove the mount
- Retire the tree manually (mv across devices with rsync) if the multi-mount layout must stay
Example fix
// before /mnt/spare mounted at ~/app/audit/shard-3 // after umount ~/app/audit/shard-3 && mv /mnt/spare/shard-3/* ~/app/audit/shard-3/
Defensive patterns
Strategy: validation
Validate before calling
use std::os::unix::fs::MetadataExt;
fn tree_on_one_device(root: &std::path::Path) -> std::io::Result<bool> {
let dev = root.symlink_metadata()?.dev();
for entry in walkdir_like(root)? {
if entry.symlink_metadata()?.dev() != dev { return Ok(false); }
}
Ok(true)
} Type guard
fn same_device(a: &std::path::Path, b: &std::path::Path) -> bool {
use std::os::unix::fs::MetadataExt;
a.symlink_metadata().map(|m| m.dev()).ok()
== b.symlink_metadata().map(|m| m.dev()).ok()
} Try / catch
if let Err(e) = run_migration() {
if e.kind() == std::io::ErrorKind::InvalidData
&& e.to_string().contains("mount boundary") {
// unmount or flatten the cross-device subtree, then retry
} else { return Err(e); }
} Prevention
- Audit /proc/mounts for mounts inside the audit tree before upgrading
- Avoid bind-mounting volumes into the audit directory
- Compare `stat -c %d` across the tree as a pre-flight check
When it happens
Trigger: Retiring the legacy audit tree when any directory inside it is a separate mount/bind mount/tmpfs, or when its st_dev differs from the audit root's device.
Common situations: Mounting audit shards onto dedicated volumes for capacity; container bind-mounts inside the audit directory; autofs triggering inside the tree during migration.
Related errors
- legacy audit source is not a regular directory
- legacy audit tree is redirected or not a directory
- legacy principal-home entry crosses a filesystem boundary
- audit fixture
- audit read failed
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/a4816d521a72ab7a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-kernel/src/lib.rs:4331
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)? {
let child = entry?.path();
let child_metadata = std::fs::symlink_metadata(&child)?;
if child_metadata.file_type().is_symlink()
|| audit_tree_device(&child_metadata) != root_device
|| audit_mountpoint(&child)?
{
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(View on GitHub (pinned to affd8760f4)