{"record":{"id":"09d1db5f2a743d89","repo":"astrid-runtime/astrid","slug":"cannot-retire-leftover-capsule-authority-while-pen","errorCode":null,"errorMessage":"cannot retire leftover capsule authority while pending transaction artifact exists at {}","messagePattern":"cannot retire leftover capsule authority while pending transaction artifact exists at (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-capsule-install/src/authority/leftover.rs","lineNumber":50,"sourceCode":"    if read_installed_authority(home, target_dir)?.is_some() {\n        return Ok(());\n    }\n    let Some(receipt) = unique_relocated_receipt(home, target_dir, manifest, workspace_targets)?\n    else {\n        return Ok(());\n    };\n    AuthorityReceiptTransaction::stage(home, target_dir, &receipt)?.commit()?;\n    Ok(())\n}\n\n/// Active leftover receipts that are not workspace-portal targets.\npub(crate) fn unmatched_active_receipts(\n    home: &AstridHome,\n    workspace_targets: &[PathBuf],\n) -> anyhow::Result<Vec<PathBuf>> {\n    let status = super::legacy_authority_receipt_status(home, workspace_targets)?;\n    if !status.pending.is_empty() {\n        bail!(\n            \"cannot retire leftover capsule authority while pending transaction artifact exists at {}\",\n            status.pending[0].display()\n        );\n    }\n    if !status.previous.is_empty() {\n        bail!(\n            \"cannot retire leftover capsule authority while previous transaction artifact exists at {}\",\n            status.previous[0].display()\n        );\n    }\n    Ok(status.unknown_active)\n}\n\n/// Parse a regular-file leftover receipt. Invalid JSON returns `Ok(None)`.\npub(crate) fn parse_legacy_authority_receipt(\n    path: &Path,\n) -> anyhow::Result<Option<(InstalledAuthority, Vec<u8>)>> {\n    let metadata = fs::symlink_metadata(path)","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-capsule-install/src/authority/leftover.rs#L32-L68","documentation":"`unmatched_active_receipts` (in the legacy/relocated-home leftover sweep) enumerates capsule-authority receipts that no longer correspond to any workspace target so they can be retired or quarantined. This error is thrown when the sweep finds a pending receipt-transaction artifact (an in-progress transaction file), which means a prior receipt write may be incomplete; retiring leftovers before that transaction resolves could corrupt authority state.","triggerScenarios":"Calling `unmatched_active_receipts` (via `retire_unmatched_legacy_authority_receipts` or the leftover-sweep tests) while `legacy_authority_receipt_status(...).pending` is non-empty — i.e. a staged but uncommitted `AuthorityReceiptTransaction` artifact exists in the authority directory (e.g. after a crash mid-transaction).","commonSituations":"A previous install/rebind crashed or was killed while committing a receipt transaction; a stale `.pending` file left behind by an interrupted process; running the migration/sweep concurrently with an active install.","solutions":["Resolve the pending transaction first: let the interrupted install finish or commit/roll back the staged `AuthorityReceiptTransaction`, then rerun the sweep","If the pending artifact is definitively stale (no install running), remove or finalize the pending file per the transaction-recovery procedure, then retry","Ensure the sweep is not run concurrently with an in-flight install holding a receipt transaction"],"exampleFix":"// before\nbail!(\"cannot retire leftover capsule authority while pending transaction artifact exists at {}\", status.pending[0].display());\n// after: recover the transaction before sweeping\n// AuthorityReceiptTransaction::recover(home)?;  // commit or roll back pending artifact\n// let leftover = unmatched_active_receipts(home, &workspace_targets)?;","handlingStrategy":"try-catch","validationCode":"// Check for pending transaction artifacts before sweeping leftovers\nlet status = legacy_authority_receipt_status(&home, &workspace_targets)?;\nif !status.pending.is_empty() {\n    // resolve the pending transaction (recover/commit) before sweeping\n}","typeGuard":null,"tryCatchPattern":"match unmatched_active_receipts(&home, &targets) {\n    Err(e) if e.to_string().contains(\"pending transaction artifact\") => {\n        AuthorityReceiptTransaction::recover(&home)?;\n        unmatched_active_receipts(&home, &targets)\n    },\n    other => other,\n}","preventionTips":["Always let interrupted installs complete or run transaction recovery after a crash","Never kill an install process mid receipt-commit","Serialize leftover sweeps with installs and migrations","Monitor the authority directory for lingering .pending files"],"tags":["transaction","authority-receipt","migration","state-conflict"],"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-14T05:17:10.506Z"}