{"record":{"id":"3d1bc58abfe80c95","repo":"astrid-runtime/astrid","slug":"fskit-lease-paths-must-be-absolute","errorCode":null,"errorMessage":"FSKit lease paths must be absolute","messagePattern":"FSKit lease paths must be absolute","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-fskit/src/service.rs","lineNumber":154,"sourceCode":"    crate::validate_mountpoint_ancestors(&launch.mountpoint)?;\n    crate::validate_unmounted_mountpoint(&launch.mountpoint)?;\n    validate_control_path(&launch.control_path, &launch.lease.resource_path)?;\n    Ok(())\n}\n\nfn validate_lease(lease: &astrid_core::storage_filesystem::StorageMountLeaseV1) -> Result<()> {\n    if lease.lease_token.len() < 16 || lease.lease_token.len() > 4096 {\n        bail!(\"FSKit lease callback token is invalid\");\n    }\n    let now = SystemTime::now()\n        .duration_since(UNIX_EPOCH)\n        .context(\"read system clock\")?\n        .as_secs();\n    if lease.expires_at_epoch_secs < now {\n        bail!(\"FSKit lease is expired\");\n    }\n    if !lease.resource_path.is_absolute() || !lease.callback_path.is_absolute() {\n        bail!(\"FSKit lease paths must be absolute\");\n    }\n    #[cfg(target_os = \"macos\")]\n    astrid_core::fskit_socket::validate_callback_path(lease.mount_id, &lease.callback_path)\n        .map_err(anyhow::Error::msg)?;\n    #[cfg(not(target_os = \"macos\"))]\n    if lease.callback_path != lease.resource_path.join(\"control.sock\") {\n        bail!(\"FSKit callback path is not the kernel lease endpoint\");\n    }\n    platform_fs::validate_private_directory(&lease.resource_path)\n        .context(\"validate private FSKit lease resource\")?;\n    platform_fs::verify_no_redirects(&lease.resource_path)\n        .context(\"reject redirected FSKit lease resource\")?;\n    platform_fs::validate_private_file(&lease.resource_path.join(\"lease.json\"))\n        .context(\"validate private FSKit lease manifest\")?;\n    let manifest = std::fs::read(lease.resource_path.join(\"lease.json\"))\n        .context(\"read FSKit lease manifest\")?;\n    if manifest.len() > 64 * 1024 {\n        bail!(\"FSKit lease manifest exceeds the bounded size\");","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-fskit/src/service.rs#L136-L172","documentation":"validate_lease requires both resource_path and callback_path on the lease to be absolute paths. Relative paths cannot be safely resolved against the kernel's view of the filesystem, so any relative component causes rejection.","triggerScenarios":"validate_lease receives a StorageMountLeaseV1 where resource_path or callback_path lacks a leading '/' (e.g. \"leases/abc\" or \"control.sock\").","commonSituations":"Relative paths from a config file written with CWD assumptions; paths built with PathBuf::from(\"relative/x\") in scripts; serialized leases where leading slashes were stripped.","solutions":["Make both paths absolute (prefix with '/') in the lease before launch","Use std::fs::canonicalize or absolute() when constructing the paths","Regenerate the lease from the provider, which always emits absolute paths"],"exampleFix":"// before\nresource_path: \"leases/mount-1\".into()\n// after\nresource_path: \"/var/fskit/leases/mount-1\".into()","handlingStrategy":"validation","validationCode":"fn paths_absolute(lease: &StorageMountLeaseV1) -> bool {\n    lease.resource_path.is_absolute() && lease.callback_path.is_absolute()\n}","typeGuard":"fn is_absolute(p: &std::path::Path) -> bool { p.is_absolute() }","tryCatchPattern":null,"preventionTips":["Canonicalize paths (std::fs::canonicalize) before constructing leases","Store absolute paths in config files; resolve relative paths at load time","Reject relative paths at config-parse time with a clear message"],"tags":["fskit","lease","paths","validation"],"backgroundTag":"invalid-argument-format","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"}