astrid-runtime/astrid · error

legacy principal-home entry crosses a filesystem boundary

Error message

legacy principal-home entry crosses a filesystem boundary: {principal_root}

What it means

During the legacy principal-home audit migration, the kernel verifies that the principal root and everything under it (via audit_tree_device/st_dev comparison) lives on a single filesystem. If the legacy principal-home entry's device ID differs from the root filesystem's device, the rename-based migration could silently lose the atomicity and write-through guarantees it relies on, so the operation is refused with InvalidData.

Solutions

  1. Move the principal-home directory onto the same filesystem/mount as the root, then re-run the migration
  2. Remove any bind mounts or symlinks-to-other-mounts that place principal_root on another device
  3. If the split is intentional, migrate the audit data manually into migrations_dir/audit-principal-home.retired so the automatic migration is skipped

Example fix

// before: principal root on a separate mount
/home/alice/.app/principal  -> mounted tmpfs volume
// after: keep the whole tree on one filesystem
/home/alice/.app/principal  (regular directory on the same device as root)
Defensive patterns

Strategy: validation

Validate before calling

use std::os::unix::fs::MetadataExt;
fn same_device(a: &std::path::Path, b: &std::path::Path) -> std::io::Result<bool> {
    Ok(a.symlink_metadata()?.dev() == b.symlink_metadata()?.dev())
}
// call before migration:
// assert!(same_device(principal_root, &root)?)

Type guard

fn is_real_dir(p: &std::path::Path) -> bool {
    std::fs::symlink_metadata(p).map(|m| m.is_dir()).unwrap_or(false)
}

Try / catch

match migrate_legacy_principal_home() {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidData
        && e.to_string().contains("filesystem boundary") => {
        eprintln!("move principal root onto one filesystem, then retry: {e}");
    }
    Err(e) => return Err(e),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: Calling the legacy principal-home migration path when the principal_root directory resides on a different mount point (different st_dev) than the filesystem root — e.g. the home directory is a separate mount, bind mount, or network share.

Common situations: Users whose home directories are automounted NFS volumes, separate /home partitions, or bind-mounted directories; containers where the principal root is a volume mount while the parent is on the container's overlay filesystem.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/16968c3cd1c0e8bc. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-kernel/src/lib.rs:4152

    };
    let root_device = audit_tree_device(&metadata);
    let mut default_source_present = false;
    astrid_core::platform_fs::verify_no_redirects(&root)?;
    for entry in std::fs::read_dir(&root)? {
        let entry = entry?;
        let principal_root = entry.path();
        let principal_metadata = std::fs::symlink_metadata(&principal_root)?;
        if principal_metadata.file_type().is_symlink() || !principal_metadata.is_dir() {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidData,
                format!(
                    "legacy principal-home entry is not a regular directory: {}",
                    principal_root.display()
                ),
            ));
        }
        if audit_tree_device(&principal_metadata) != root_device {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidData,
                format!(
                    "legacy principal-home entry crosses a filesystem boundary: {}",
                    principal_root.display()
                ),
            ));
        }
        astrid_core::platform_fs::verify_no_redirects(&principal_root)?;
        let local_root = principal_root.join(".local");
        match std::fs::symlink_metadata(&local_root) {
            Ok(metadata) if metadata.file_type().is_symlink() || !metadata.is_dir() => {
                return Err(std::io::Error::new(
                    std::io::ErrorKind::InvalidData,
                    format!(
                        "legacy principal .local path is not a directory: {}",
                        local_root.display()
                    ),
                ));

View on GitHub (pinned to affd8760f4)