{"record":{"id":"83a5cec8ef90234a","repo":"astrid-runtime/astrid","slug":"mountpoint-is-not-empty-83a5ce","errorCode":null,"errorMessage":"mountpoint is not empty: {}","messagePattern":"mountpoint is not empty: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-fuse/src/mountpoint.rs","lineNumber":55,"sourceCode":"    let metadata = std::fs::symlink_metadata(&requested)?;\n    if !metadata.is_dir() {\n        bail!(\"mountpoint is not a directory: {}\", requested.display());\n    }\n    let expected_uid = u32::from(getuid());\n    if metadata.uid() != expected_uid {\n        bail!(\n            \"mountpoint must be owned by the current OS user: {}\",\n            requested.display()\n        );\n    }\n    let mode = metadata.permissions().mode();\n    if !existed {\n        std::fs::set_permissions(&requested, Permissions::from_mode(0o700))?;\n    } else if mode & 0o077 != 0 {\n        bail!(\"mountpoint must be owner-private: {}\", requested.display());\n    }\n    if std::fs::read_dir(&requested)?.next().is_some() {\n        bail!(\"mountpoint is not empty: {}\", requested.display());\n    }\n    let canonical = requested\n        .canonicalize()\n        .with_context(|| format!(\"canonicalize mountpoint {}\", requested.display()))?;\n    if mountinfo_contains(&canonical)? {\n        bail!(\"mountpoint is already mounted: {}\", canonical.display());\n    }\n    Ok((canonical, !existed))\n}\n\n/// Return current owner identity for synthetic inode metadata.\npub(crate) fn owner_ids() -> (u32, u32) {\n    (getuid().into(), getgid().into())\n}\n\n/// Remove a dead FUSE mount if one remains at an exact canonical path.\npub(crate) fn lazy_unmount(mountpoint: &Path) -> Result<()> {\n    use nix::mount::MntFlags;","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-fuse/src/mountpoint.rs#L37-L73","documentation":"prepare_mountpoint refuses to mount over a non-empty directory. After enforcing permissions it reads the directory and bails if any entry exists, since mounting over populated directories hides their contents and can hide stale data.","triggerScenarios":"Calling the mount flow with an existing directory that contains files or subdirectories (leftovers from a previous run, user files, or a lost+found).","commonSituations":"Re-running after a crashed session left artifacts in the mountpoint; pointing the mount at a directory already holding user data; stale files left by a failed rollback.","solutions":["Empty the directory (rm -rf <mountpoint>/* including dotfiles) before mounting","Remove and recreate the directory so the provider creates a fresh private one","Recover files from a previous failed mount before retrying","Check for leftover session artifacts (e.g. from rollback cleanup failures)"],"exampleFix":"// before\nls /mnt/myfuse  # stale session files remain\n// after\nrm -rf /mnt/myfuse && mkdir -m 700 /mnt/myfuse","handlingStrategy":"validation","validationCode":"fn mountpoint_is_empty(path: &std::path::Path) -> std::io::Result<bool> {\n    Ok(std::fs::read_dir(path)?.next().is_none())\n}","typeGuard":null,"tryCatchPattern":"match prepare_mountpoint(&path) {\n    Err(e) if e.to_string().contains(\"not empty\") => {\n        eprintln!(\"empty {} (check for stale session artifacts) first\", path.display());\n    }\n    other => other?,\n}","preventionTips":["Use one dedicated empty directory per mount session","Clean up artifacts after each session, including after crashes","Never point a FUSE mount at a directory holding user data","Inspect for lost+found or leftover files when reusing OS-managed directories"],"tags":["fuse","filesystem","mount"],"backgroundTag":"file-already-exists","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"}