astrid-runtime/astrid · error

{}

Error message

{}

What it means

finish_cleanup aggregates every failure that occurred while detaching the mountpoint and removing leftover artifacts; if any step failed it joins the messages with "; " and bails with that combined message. The error text is therefore the joined list of cleanup failures, not a single cause.

Source

Thrown at crates/astrid-storage-provider-fuse/src/rollback.rs:33

}

pub(crate) fn finish_cleanup(
    mut failures: Vec<String>,
    detach: Result<()>,
    cleanup: impl FnOnce() -> Result<()>,
) -> Result<()> {
    match detach {
        Ok(()) => {
            if let Err(error) = cleanup() {
                failures.push(format!("remove service artifacts: {error:#}"));
            }
        },
        Err(error) => failures.push(format!("detach mountpoint: {error:#}")),
    }
    if failures.is_empty() {
        Ok(())
    } else {
        bail!("{}", failures.join("; "))
    }
}

#[cfg(test)]
mod tests {
    use std::cell::Cell;

    use super::*;

    #[test]
    fn failed_detach_retains_artifacts_and_preserves_every_failure() {
        let cleanup_called = Cell::new(false);
        let rollback = finish_cleanup(
            vec![
                "control unmount: refused".to_owned(),
                "revoke mount lease: denied".to_owned(),
            ],
            Err(anyhow::anyhow!("busy")),

View on GitHub (pinned to affd8760f4)

Solutions

  1. Read the joined messages to identify each failed sub-step and fix them individually
  2. Retry the detach after resolving why the mount was busy (check lsof/fuser on the mountpoint)
  3. Manually remove leftover artifacts (mountpoint directory) with correct permissions
  4. Check for permission issues for the user running cleanup

Example fix

// before
# cleanup fails: detach mountpoint: EBUSY; remove artifacts: permission denied
// after
fusermount -u -z /mnt/fuse && rm -rf /mnt/fuse  # then retry operation
Defensive patterns

Strategy: try-catch

Try / catch

match finish_cleanup(steps) {
    Err(e) => {
        for failure in e.to_string().split("; ") {
            eprintln!("cleanup step failed: {failure}");
        }
    }
    Ok(()) => {}
}

Prevention

When it happens

Trigger: Any cleanup step failing during rollback: umount2 error, failure removing the mountpoint directory, or other artifact-removal errors; multiple failures are concatenated.

Common situations: Mount still busy so MNT_DETACH errors; filesystem permission problems preventing artifact removal; NFS/network filesystems delaying unmount; multiple cascading failures after a failed launch.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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