astrid-runtime/astrid · error

detached FUSE service failed: {message}

Error message

detached FUSE service failed: {message}

What it means

This wraps a structured failure reported by the FUSE service itself. The child mounted nothing, sent ServiceStartup::Error { message } over stdout, and the parent re-raises that message prefixed with context. The root cause text after the colon comes from inside the service (FUSE mount failure, permission denied on the mountpoint, kernel registration rejection, etc.).

Source

Thrown at crates/astrid-storage-provider-fuse/src/main.rs:724

    match serde_json::from_str(&line)? {
        ServiceStartup::Ready {
            mount_id,
            pid,
            access,
        } => {
            if !control_path.exists() {
                bail!("detached FUSE service did not retain its control endpoint");
            }
            if pid == 0 {
                bail!("detached FUSE service returned an invalid process identity");
            }
            Ok(ControlReady {
                mount_id,
                pid,
                access,
            })
        },
        ServiceStartup::Error { message } => bail!("detached FUSE service failed: {message}"),
    }
}

#[derive(Debug)]
struct ControlReady {
    mount_id: StorageMountId,
    pid: u32,
    access: StorageProviderAccessV1,
}

#[derive(Debug, Deserialize)]
struct LeaseStatus {
    #[allow(dead_code)]
    mount_id: StorageMountId,
    access: StorageProviderAccessV1,
    mountpoint: PathBuf,
    dirty: bool,
}

View on GitHub (pinned to affd8760f4)

Solutions

  1. Read the embedded {message} in the error — it names the service-side root cause; fix that directly
  2. Verify the mountpoint exists, is an empty directory, and is not already mounted
  3. Check FUSE availability: fuse kernel module loaded, fusermount3 installed, unprivileged mounts enabled
  4. Confirm parent and service binaries are from the same version so the launch JSON deserializes

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight checks before launching the service
if !mountpoint.exists() { return Err(anyhow!("mountpoint {} does not exist", mountpoint.display())); }
if mountpoint_is_busy(mountpoint)? { return Err(anyhow!("mountpoint already in use")); }
ensure_fuse_available()?; // fusermount3 present, module loaded, unprivileged mounts allowed

Try / catch

match start_detached_service(&launch).await {
    Err(e) if e.to_string().contains("detached FUSE service failed:") => {
        let cause = e.to_string().split("detached FUSE service failed: ").nth(1).unwrap_or("");
        eprintln!("service-side failure: {cause}"); // act on the embedded root cause
    }
    Err(e) => return Err(e),
    Ok(ready) => use_mount(ready),
}

Prevention

When it happens

Trigger: The detached FUSE service fails during startup and deliberately reports it: fuse mount syscall fails, mountpoint doesn't exist or is busy, kernel storage-mount lease cannot be acquired, launch config deserialization fails inside the service.

Common situations: Mountpoint directory missing or already in use; fusermount/fuse kernel module unavailable or unprivileged user mounts disabled (/proc/sys/fs/unprivileged_userfusermount); stale registry entry pointing at a dead lease; malformed launch JSON from a version mismatch.

Related errors


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