astrid-runtime/astrid · error

FUSE lease paths must be absolute

Error message

FUSE lease paths must be absolute

What it means

The lease's `resource_path` (where lease artifacts live) and `callback_path` (the control socket) must both be absolute paths. Relative paths cannot be safely shared between the parent and helper processes (different working directories) and are rejected at validation.

Solutions

  1. Canonicalize paths with `std::fs::canonicalize` or join them onto an absolute base (e.g. `/run/...` or `std::env::temp_dir()`) before writing the lease.
  2. Expand `~` and env vars when loading mount configuration.
  3. Pass absolute paths from the parent process into the lease instead of CWD-relative values.
  4. Assert path absoluteness at lease-creation time to fail early.

Example fix

// before
resource_path: PathBuf::from("runtime/fuse/mount"),
// after
let base = std::env::temp_dir().join("astrid-fuse");
resource_path: base.canonicalize().unwrap_or(base), // absolute
Defensive patterns

Strategy: validation

Validate before calling

fn paths_are_absolute(lease: &StorageMountLeaseV1) -> bool {
    lease.resource_path.is_absolute() && lease.callback_path.is_absolute()
}
if !paths_are_absolute(&lease) { return Err("lease paths must be absolute"); }

Type guard

fn has_absolute_paths(lease: &StorageMountLeaseV1) -> bool {
    lease.resource_path.is_absolute() && lease.callback_path.is_absolute()
}

Prevention

When it happens

Trigger: `validate_lease` finds `!lease.resource_path.is_absolute() || !lease.callback_path.is_absolute()` during `validate_launch`.

Common situations: Caller built paths from a relative CWD (e.g. "runtime/fuse/mount"); paths came from config with `~` unexpanded; a template placeholder left unsubstituted; the parent process ran with a different working directory than intended.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/a27fdb7592501323. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-storage-provider-fuse/src/service.rs:219

    Ok(())
}

fn validate_lease(lease: &StorageMountLeaseV1) -> Result<()> {
    if lease.lease_token.len() < 16
        || lease.lease_token.len() > 4096
        || lease.lease_token.chars().any(char::is_control)
    {
        bail!("invalid FUSE callback token");
    }
    let now = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .context("read system clock")?
        .as_secs();
    if lease.expires_at_epoch_secs < now {
        bail!("FUSE lease is expired");
    }
    if !lease.resource_path.is_absolute() || !lease.callback_path.is_absolute() {
        bail!("FUSE lease paths must be absolute");
    }
    if lease.callback_path != lease.resource_path.join("control.sock") {
        bail!("FUSE callback path is not the kernel lease endpoint");
    }
    platform_fs::validate_private_directory(&lease.resource_path)
        .context("validate private FUSE lease resource")?;
    platform_fs::verify_no_redirects(&lease.resource_path)
        .context("reject redirected FUSE lease resource")?;
    let manifest_path = lease.resource_path.join("lease.json");
    platform_fs::validate_private_file(&manifest_path)
        .context("validate private FUSE lease manifest")?;
    let manifest = std::fs::read(&manifest_path).context("read FUSE lease manifest")?;
    if manifest.len() > 64 * 1024 {
        bail!("FUSE lease manifest exceeds the bounded size");
    }
    let admitted: StorageMountLeaseV1 =
        serde_json::from_slice(&manifest).context("decode FUSE lease manifest")?;
    if admitted != *lease {

View on GitHub (pinned to affd8760f4)