astrid-runtime/astrid · error

FUSE service unmount failed [{code}]: {message}

Error message

FUSE service unmount failed [{code}]: {message}

What it means

When unmounting, the FUSE control service can reject the request with a ControlResponse::Failure carrying a code and message. The client propagates that failure as this bail in crates/astrid-storage-provider-fuse/src/main.rs:875, embedding the service-side code and message.

Source

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

    registry::remove_record(&record.mount_id)?;
    cleanup_service_artifacts(
        &record.control_path,
        &record.mountpoint,
        record.auto_created_mountpoint,
    )?;
    Ok(())
}

fn control_unmount(control_path: &Path, acting_principal: &astrid_core::PrincipalId) -> Result<()> {
    match call_control(
        control_path,
        &ControlRequest::Unmount {
            requested_by: acting_principal.clone(),
        },
    )? {
        ControlResponse::Done => Ok(()),
        ControlResponse::Failure { code, message } => {
            bail!("FUSE service unmount failed [{code}]: {message}")
        },
        ControlResponse::Status { .. } => {
            bail!("FUSE service returned an incompatible unmount response")
        },
    }
}

fn cleanup_mountpoint(mountpoint: &Path, auto_created: bool) -> Result<()> {
    if auto_created
        && !mountpoint::mountinfo_contains(mountpoint)?
        && std::fs::symlink_metadata(mountpoint).is_ok_and(|metadata| metadata.is_dir())
        && std::fs::read_dir(mountpoint)?.next().is_none()
    {
        let _ = std::fs::remove_dir(mountpoint);
    }
    Ok(())
}

View on GitHub (pinned to affd8760f4)

Solutions

  1. Read the embedded [code] and {message} from the error to identify the service-side cause and fix that first (e.g. close files, correct principal)
  2. Retry the unmount after ensuring no processes hold open files under the mountpoint (fuser -v <mountpoint>)
  3. If the service is stale, force-terminate the FUSE daemon and clean up the mountpoint/record manually, then remount cleanly

Example fix

// before
unmount(...)?; // FUSE service unmount failed [EBUSY]: device busy
// after
ensure_no_open_handles(mountpoint)?; // e.g. run fuser/lsof check
unmount(...)?;
Defensive patterns

Strategy: try-catch

Validate before calling

if has_open_handles(mountpoint) { bail!("close handles before unmount") }

Type guard

fn is_failure(resp: &ControlResponse) -> Option<(u32, String)> { match resp { ControlResponse::Failure { code, message } => Some((*code, message.clone())), _ => None } }

Try / catch

match unmount(...) { Err(e) if e.to_string().starts_with("FUSE service unmount failed") => { log_service_code(&e); handle_service_failure(&e) }, r => r? }

Prevention

When it happens

Trigger: Calling the unmount path while the FUSE service refuses the Unmount request — e.g. the mountpoint is still busy, the requesting principal (requested_by) is not authorized, or the service has no active mount.

Common situations: Open file handles keep the mount busy; a different user tries to unmount another principal's mount; the kernel-level FUSE mount already died but the service still tracks it.

Related errors


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