{"record":{"id":"5f2606e8bdd7f74f","repo":"astrid-runtime/astrid","slug":"legacy-state-source-crosses-a-filesystem-boundary","errorCode":null,"errorMessage":"legacy state source crosses a filesystem boundary: {}","messagePattern":"legacy state source crosses a filesystem boundary: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-core/src/dirs_layout_retirement.rs","lineNumber":236,"sourceCode":"    // later operator repair or an idempotent restart.\n    let root_device = legacy_tree_device(&metadata);\n    validate_legacy_tree(path, root_device)?;\n    delete_legacy_tree(path, root_device)?;\n    let parent = path\n        .parent()\n        .ok_or_else(|| io::Error::other(\"legacy state source has no parent\"))?;\n    sync_directory(parent)\n}\n\nfn ensure_legacy_tree_boundary(\n    path: &Path,\n    root_device: u64,\n    metadata: &std::fs::Metadata,\n) -> io::Result<()> {\n    #[cfg(unix)]\n    {\n        if legacy_tree_device(metadata) != root_device {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\n                    \"legacy state source crosses a filesystem boundary: {}\",\n                    path.display()\n                ),\n            ));\n        }\n    }\n    #[cfg(not(unix))]\n    let _ = (root_device, metadata);\n    if is_active_mountpoint(path)? {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            format!(\"legacy state source is an active mount: {}\", path.display()),\n        ));\n    }\n    Ok(())\n}","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-core/src/dirs_layout_retirement.rs#L218-L254","documentation":"ensure_legacy_tree_boundary compares the st_dev of each directory in the legacy tree against the root device. If any entry lies on a different filesystem (i.e. the tree crosses a mount boundary), it throws InvalidData so deletion never recurses into a separate filesystem and wipes unrelated data.","triggerScenarios":"Any subdirectory inside the legacy tree is a mountpoint or was bind-mounted from another device when validate_legacy_tree or delete_legacy_tree checks boundaries.","commonSituations":"An admin mounted extra storage at a nested state subdirectory (e.g. tmpfs at legacy/tmp); Docker/Kubernetes volume mounts placed inside the data dir; disk re-partitioning moved part of the tree.","solutions":["Unmount the nested filesystem (umount <reported path>) so the whole tree lives on one device, then retry.","Relocate the mounted content into the same filesystem and re-check.","Use a bind mount at the tree root itself is NOT allowed either — the entire tree must be on one device, so flatten the layout."],"exampleFix":"// before\nmount | grep legacy  -> tmpfs on /data/legacy/tmp\n// after\numount /data/legacy/tmp","handlingStrategy":"validation","validationCode":"#[cfg(unix)]\nfn same_device(p: &Path, root_dev: u64) -> io::Result<bool> {\n    use std::os::unix::fs::MetadataExt;\n    Ok(std::fs::metadata(p)?.dev() == root_dev)\n}","typeGuard":"fn crosses_boundary(md: &std::fs::Metadata, root_dev: u64) -> bool {\n    use std::os::unix::fs::MetadataExt;\n    md.dev() != root_dev\n}","tryCatchPattern":"match retire_legacy_source_tree(&path, dev) {\n    Err(e) if e.to_string().contains(\"filesystem boundary\") => eprintln!(\"umount nested fs first\"),\n    other => other?,\n}","preventionTips":["Never mount volumes inside legacy state subdirectories","Run `df <path>` / `stat -c %d` checks before retirement","Keep container volume mounts at or above the state root, not within it"],"tags":["rust","mount","filesystem"],"backgroundTag":"filesystem-boundary-crossing","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}