astrid-runtime/astrid · error
legacy audit tree crosses a filesystem or mount boundary: {}
Error message
legacy audit tree crosses a filesystem or mount boundary: {} What it means
validate_audit_tree enforces that the whole legacy audit tree lives on one filesystem: each node's device id must equal the root device and the node must not itself be an active mountpoint. A violation means part of the tree sits on another mount (bind mount, network share, tmpfs), so a same-filesystem rename-based retirement would be incomplete or could silently move only part of the data.
Source
Thrown at crates/astrid-kernel/src/legacy_migration_barrier/host_fs.rs:523
Err(error) => return Err(error),
}
Ok(())
}
#[cfg(not(unix))]
fn validate_audit_tree(path: &Path, root_device: u64) -> io::Result<()> {
let metadata = fs::symlink_metadata(path)?;
if metadata.file_type().is_symlink() || !metadata.is_dir() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"legacy audit tree is redirected or not a directory: {}",
path.display()
),
));
}
if device_id(&metadata) != root_device || active_mountpoint(path)? {
return Err(io::Error::new(
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 fs::read_dir(path).map_err(io::Error::other)? {
let child = entry.map_err(io::Error::other)?.path();
let child_metadata = fs::symlink_metadata(&child).map_err(io::Error::other)?;
if child_metadata.file_type().is_symlink()
|| device_id(&child_metadata) != root_device
|| active_mountpoint(&child)?
{
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(View on GitHub (pinned to affd8760f4)
Solutions
- Unmount the mount covering the audit path (umount) so the tree is a single filesystem, then re-run migration.
- Move the audit data onto the same filesystem as the principal home and remove the external mount.
- If the data must stay on another filesystem, consolidate it into the default location before migration.
Example fix
// before mount --bind /mnt/data/audit ~/.astrid/principal/audit // after umount ~/.astrid/principal/audit # data lives directly on the home filesystem
Defensive patterns
Strategy: validation
Validate before calling
fn same_device(root: &Path) -> std::io::Result<bool> {
use std::os::unix::fs::MetadataExt;
let r = std::fs::symlink_metadata(root)?;
for entry in std::fs::read_dir(root)? {
if std::fs::symlink_metadata(entry?.path())?.dev() != r.dev() { return Ok(false); }
}
Ok(true)
} Try / catch
if let Err(e) = migrate_legacy_audit(&home, &source) {
if e.to_string().contains("filesystem or mount boundary") {
// findmnt to locate the mount, unmount it, then retry
}
} Prevention
- Never bind-mount or NFS-mount paths under ~/.astrid.
- Check `findmnt --target <audit-dir>` before migrating.
- Keep audit data on the same filesystem as the principal home.
When it happens
Trigger: Any validate_audit_tree caller (preflight, retire, recursive descent, delete) encountering a node whose st_dev differs from the root device, or a path that is an active mountpoint — e.g. the audit dir or a subtree is bind-mounted or on a separate partition/NFS mount.
Common situations: Users mounting a separate disk or NFS share at ~/.astrid/audit; bind mounts in containers; tmpfs mounted over part of the tree; encrypted-home setups mounting subtrees.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- legacy source is an active mount: {}
- legacy source crosses a mount or device boundary: {}
- legacy principal-home entry crosses a filesystem boundary: {
- legacy capsule directory is not a regular directory: {}
- legacy capsule entry is not a regular directory: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/c1211cdf800d8931.
Report an issue: GitHub.