astrid-runtime/astrid · warning

mount rollback incomplete: {}

Error message

mount rollback incomplete: {}

What it means

Rollback succeeded in unmounting the native filesystem, but at least one teardown step (revoke, registry removal, or mountpoint cleanup) recorded an error. The system is consistent enough (native unmount done) yet the message lists which follow-up steps failed, joined with '; '.

Source

Thrown at crates/astrid-storage-provider-fskit/src/main.rs:348

    rollback: Result<()>,
) -> Result<StorageProviderSuccessV1> {
    match rollback {
        Ok(()) => Err(error),
        Err(rollback) => Err(error).context(rollback),
    }
}

fn rollback_outcome(native_unmounted: bool, errors: &[String]) -> Result<()> {
    if !native_unmounted {
        bail!(
            "mount rollback left the lease registered for recovery; {}",
            errors.join("; ")
        );
    }
    if errors.is_empty() {
        return Ok(());
    }
    bail!("mount rollback incomplete: {}", errors.join("; "))
}

async fn rollback_after_native_failure(
    client: &mut AdminClient,
    mount_id: &StorageMountId,
    mountpoint: &Path,
    auto_created: bool,
    native_mount_command_succeeded: bool,
) -> Result<()> {
    let mut errors = Vec::new();
    let native_unmounted = if native_mount_command_succeeded {
        match native_unmount(mountpoint).await {
            Ok(()) => true,
            Err(error) => {
                errors.push(format!("unmount: {error:#}"));
                false
            },
        }

View on GitHub (pinned to affd8760f4)

Solutions

  1. Read the joined reasons to see which step failed (revoke/registry/cleanup).
  2. If revoke failed, call StorageMountRevoke manually once the kernel is reachable (mirroring revoke_after_registry_failure).
  3. If registry removal failed, delete the stale entry on next run or fix registry file permissions/locks.
  4. If cleanup failed, remove the leftover empty directory manually once nothing references it.
Defensive patterns

Strategy: retry

Try / catch

if let Err(e) = rollback_after_native_failure(...).await {
    if e.to_string().contains("mount rollback incomplete") {
        // parse joined reasons; retry revoke/registry/cleanup steps individually
    }
}

Prevention

When it happens

Trigger: In rollback_after_native_failure(), the StorageMountRevoke request, update_registry() removal, or cleanup_created_mountpoint() returns Err after a successful native unmount; rollback_outcome(true, errors) bails with the joined errors.

Common situations: Kernel unreachable for the revoke call right after unmount; registry file locked or on a read-only volume; auto-created mountpoint already partially removed by another process, making cleanup fail.

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/08e7b48f06482659. Report an issue: GitHub.