{"record":{"id":"89785aaf7ba72b08","repo":"astrid-runtime/astrid","slug":"mountpoint-must-be-absolute","errorCode":null,"errorMessage":"mountpoint must be absolute","messagePattern":"mountpoint must be absolute","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-fskit/src/main.rs","lineNumber":527,"sourceCode":"            bail!(\n                \"mountpoint ancestor is writable without sticky protection: {}\",\n                path.display()\n            );\n        }\n        ancestor = path.parent();\n    }\n    Ok(())\n}\n\n#[cfg(not(unix))]\nfn validate_mountpoint_ancestors(mountpoint: &Path) -> Result<()> {\n    let _ = mountpoint;\n    Ok(())\n}\n\nfn validate_mountpoint_layout(mountpoint: &Path) -> Result<()> {\n    if !mountpoint.is_absolute() {\n        bail!(\"mountpoint must be absolute\");\n    }\n    if mountpoint.components().any(|component| {\n        matches!(\n            component,\n            std::path::Component::ParentDir | std::path::Component::CurDir\n        )\n    }) {\n        bail!(\"mountpoint contains traversal: {}\", mountpoint.display());\n    }\n    if mountpoint.parent().is_none() {\n        bail!(\"mountpoint must be below a parent directory\");\n    }\n    Ok(())\n}\n\n#[cfg(target_os = \"macos\")]\npub(crate) async fn native_mount(lease: &StorageMountLeaseV1, mountpoint: &Path) -> Result<()> {\n    let output = tokio::process::Command::new(\"/sbin/mount\")","sourceCodeStart":509,"sourceCodeEnd":545,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-fskit/src/main.rs#L509-L545","documentation":"validate_mountpoint_layout rejects any mountpoint path that is not absolute before any mount/unmount operation. Relative paths are ambiguous because the FSKit helper service may run with a different working directory than the caller, so the provider requires a fully-qualified path. The check runs on every mount, unmount, and validation path.","triggerScenarios":"Passing a relative path (e.g. \"mnt/fs\") as the mountpoint argument to mount, unmount, prepare_mountpoint, validate_mounted_mountpoint, or validate_unmounted_mountpoint.","commonSituations":"Building the mountpoint from a user-supplied CLI flag without canonicalizing it; calling the provider from a script whose cwd differs from the service's; forgetting to join a base directory with Path::join or abs_path.","solutions":["Pass an absolute path such as /Volumes/fskit-mnt instead of a relative one","Canonicalize in the caller: std::fs::canonicalize or std::path::absolute before invoking the provider","If mounting a new empty dir, build the absolute path explicitly from root, e.g. PathBuf::from(\"/Volumes\").join(name)"],"exampleFix":"// before\nlet mountpoint = Path::new(\"mnt/fskit\");\n// after\nlet mountpoint = std::path::absolute(\"mnt/fskit\")?; // e.g. /work/mnt/fskit","handlingStrategy":"validation","validationCode":"fn ensure_absolute(mp: &std::path::Path) -> anyhow::Result<()> {\n    anyhow::ensure!(mp.is_absolute(), \"mountpoint must be absolute: {}\", mp.display());\n    Ok(())\n}","typeGuard":"fn is_absolute_path(p: &str) -> bool { std::path::Path::new(p).is_absolute() }","tryCatchPattern":null,"preventionTips":["Canonicalize user-supplied paths with std::path::absolute before calling the provider","Reject relative mountpoint flags at CLI parse time","Build mountpoints with PathBuf::from(\"/Volumes\").join(name) instead of raw strings"],"tags":["filesystem","path-validation","mount"],"backgroundTag":"invalid-argument-value","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"}