{"record":{"id":"08e7b48f06482659","repo":"astrid-runtime/astrid","slug":"mount-rollback-incomplete","errorCode":null,"errorMessage":"mount rollback incomplete: {}","messagePattern":"mount rollback incomplete: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/astrid-storage-provider-fskit/src/main.rs","lineNumber":348,"sourceCode":"    rollback: Result<()>,\n) -> Result<StorageProviderSuccessV1> {\n    match rollback {\n        Ok(()) => Err(error),\n        Err(rollback) => Err(error).context(rollback),\n    }\n}\n\nfn rollback_outcome(native_unmounted: bool, errors: &[String]) -> Result<()> {\n    if !native_unmounted {\n        bail!(\n            \"mount rollback left the lease registered for recovery; {}\",\n            errors.join(\"; \")\n        );\n    }\n    if errors.is_empty() {\n        return Ok(());\n    }\n    bail!(\"mount rollback incomplete: {}\", errors.join(\"; \"))\n}\n\nasync fn rollback_after_native_failure(\n    client: &mut AdminClient,\n    mount_id: &StorageMountId,\n    mountpoint: &Path,\n    auto_created: bool,\n    native_mount_command_succeeded: bool,\n) -> Result<()> {\n    let mut errors = Vec::new();\n    let native_unmounted = if native_mount_command_succeeded {\n        match native_unmount(mountpoint).await {\n            Ok(()) => true,\n            Err(error) => {\n                errors.push(format!(\"unmount: {error:#}\"));\n                false\n            },\n        }","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-fskit/src/main.rs#L330-L366","documentation":"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 '; '.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the joined reasons to see which step failed (revoke/registry/cleanup).","If revoke failed, call StorageMountRevoke manually once the kernel is reachable (mirroring revoke_after_registry_failure).","If registry removal failed, delete the stale entry on next run or fix registry file permissions/locks.","If cleanup failed, remove the leftover empty directory manually once nothing references it."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = rollback_after_native_failure(...).await {\n    if e.to_string().contains(\"mount rollback incomplete\") {\n        // parse joined reasons; retry revoke/registry/cleanup steps individually\n    }\n}","preventionTips":["Make revoke idempotent and retry it on failure (as revoke_after_registry_failure does).","Keep the registry file on writable local storage with proper locking.","Re-check the auto-created mountpoint before cleanup to avoid racing removals.","Alert on this error and reconcile state (revoke + registry removal) in a follow-up task."],"tags":["rollback","cleanup","partial-failure"],"backgroundTag":"invalid-state-transition","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}