{"record":{"id":"a4816d521a72ab7a","repo":"astrid-runtime/astrid","slug":"legacy-audit-tree-crosses-a-filesystem-or-mount-bo-a4816d","errorCode":null,"errorMessage":"legacy audit tree crosses a filesystem or mount boundary: {path}","messagePattern":"legacy audit tree crosses a filesystem or mount boundary: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/lib.rs","lineNumber":4331,"sourceCode":"    use std::os::unix::fs::MetadataExt as _;\n\n    metadata.dev()\n}\n\n#[cfg(unix)]\nfn validate_audit_tree(path: &Path, root_device: u64) -> std::io::Result<()> {\n    let metadata = std::fs::symlink_metadata(path)?;\n    if metadata.file_type().is_symlink() || !metadata.is_dir() {\n        return Err(std::io::Error::new(\n            std::io::ErrorKind::InvalidData,\n            format!(\n                \"legacy audit tree is redirected or not a directory: {}\",\n                path.display()\n            ),\n        ));\n    }\n    if audit_tree_device(&metadata) != root_device || audit_mountpoint(path)? {\n        return Err(std::io::Error::new(\n            std::io::ErrorKind::InvalidData,\n            format!(\n                \"legacy audit tree crosses a filesystem or mount boundary: {}\",\n                path.display()\n            ),\n        ));\n    }\n    astrid_core::platform_fs::verify_no_redirects(path)?;\n    for entry in std::fs::read_dir(path)? {\n        let child = entry?.path();\n        let child_metadata = std::fs::symlink_metadata(&child)?;\n        if child_metadata.file_type().is_symlink()\n            || audit_tree_device(&child_metadata) != root_device\n            || audit_mountpoint(&child)?\n        {\n            return Err(std::io::Error::new(\n                std::io::ErrorKind::InvalidData,\n                format!(","sourceCodeStart":4313,"sourceCodeEnd":4349,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/lib.rs#L4313-L4349","documentation":"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.","triggerScenarios":"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.","commonSituations":"Mounting audit shards onto dedicated volumes for capacity; container bind-mounts inside the audit directory; autofs triggering inside the tree during migration.","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"],"exampleFix":"// before\n/mnt/spare mounted at ~/app/audit/shard-3\n// after\numount ~/app/audit/shard-3 && mv /mnt/spare/shard-3/* ~/app/audit/shard-3/","handlingStrategy":"validation","validationCode":"use std::os::unix::fs::MetadataExt;\nfn tree_on_one_device(root: &std::path::Path) -> std::io::Result<bool> {\n    let dev = root.symlink_metadata()?.dev();\n    for entry in walkdir_like(root)? {\n        if entry.symlink_metadata()?.dev() != dev { return Ok(false); }\n    }\n    Ok(true)\n}","typeGuard":"fn same_device(a: &std::path::Path, b: &std::path::Path) -> bool {\n    use std::os::unix::fs::MetadataExt;\n    a.symlink_metadata().map(|m| m.dev()).ok()\n        == b.symlink_metadata().map(|m| m.dev()).ok()\n}","tryCatchPattern":"if let Err(e) = run_migration() {\n    if e.kind() == std::io::ErrorKind::InvalidData\n        && e.to_string().contains(\"mount boundary\") {\n        // unmount or flatten the cross-device subtree, then retry\n    } else { return Err(e); }\n}","preventionTips":["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"],"tags":["filesystem","mount-boundary","audit","rust"],"backgroundTag":"cross-filesystem-boundary","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T20:17:13.540Z"}