astrid-runtime/astrid · error
cannot retire leftover capsule authority while previous tran
Error message
cannot retire leftover capsule authority while previous transaction artifact exists at {} What it means
Like the pending check, `unmatched_active_receipts` refuses to sweep when a *previous* receipt-transaction artifact exists. The previous-generation file is the backup of the receipt that a transaction intended to replace; its presence means a transaction has not fully completed (or crashed between commit and cleanup), and retiring leftover receipts now could destroy data needed for recovery.
Source
Thrown at crates/astrid-capsule-install/src/authority/leftover.rs:56
};
AuthorityReceiptTransaction::stage(home, target_dir, &receipt)?.commit()?;
Ok(())
}
/// Active leftover receipts that are not workspace-portal targets.
pub(crate) fn unmatched_active_receipts(
home: &AstridHome,
workspace_targets: &[PathBuf],
) -> anyhow::Result<Vec<PathBuf>> {
let status = super::legacy_authority_receipt_status(home, workspace_targets)?;
if !status.pending.is_empty() {
bail!(
"cannot retire leftover capsule authority while pending transaction artifact exists at {}",
status.pending[0].display()
);
}
if !status.previous.is_empty() {
bail!(
"cannot retire leftover capsule authority while previous transaction artifact exists at {}",
status.previous[0].display()
);
}
Ok(status.unknown_active)
}
/// Parse a regular-file leftover receipt. Invalid JSON returns `Ok(None)`.
pub(crate) fn parse_legacy_authority_receipt(
path: &Path,
) -> anyhow::Result<Option<(InstalledAuthority, Vec<u8>)>> {
let metadata = fs::symlink_metadata(path)
.with_context(|| format!("inspect leftover capsule authority {}", path.display()))?;
if metadata.file_type().is_symlink() || !metadata.is_file() {
bail!(
"leftover capsule authority receipt is not a regular file: {}",
path.display()
);View on GitHub (pinned to affd8760f4)
Solutions
- Complete transaction recovery: restore/commit or safely discard the previous-generation artifact, then rerun the sweep
- If no transaction is active and the artifact is stale, remove it per the documented recovery procedure and retry
- Serialize the leftover sweep with installs/migrations so transactions can never be mid-flight
Example fix
// before
bail!("cannot retire leftover capsule authority while previous transaction artifact exists at {}", status.previous[0].display());
// after: finish the interrupted transaction first
// AuthorityReceiptTransaction::recover(home)?;
// let leftover = unmatched_active_receipts(home, &workspace_targets)?; Defensive patterns
Strategy: try-catch
Validate before calling
// Check for previous-generation transaction artifacts before sweeping
let status = legacy_authority_receipt_status(&home, &workspace_targets)?;
if !status.previous.is_empty() {
// finish or discard the interrupted transaction before sweeping
} Try / catch
match unmatched_active_receipts(&home, &targets) {
Err(e) if e.to_string().contains("previous transaction artifact") => {
AuthorityReceiptTransaction::recover(&home)?;
unmatched_active_receipts(&home, &targets)
},
other => other,
} Prevention
- Run transaction recovery after any crash or SIGKILL of an install
- Ensure adequate disk space so commit cleanup can't fail midway
- Avoid running migration/sweep concurrently with installs
- Alert on .previous artifacts persisting in the authority directory
When it happens
Trigger: Calling `unmatched_active_receipts` (via `retire_unmatched_legacy_authority_receipts`) while `legacy_authority_receipt_status(...).previous` is non-empty — a `.previous` transaction artifact remains at the reported path, typically from an interrupted or crashed receipt commit.
Common situations: Crash or SIGKILL during the two-phase receipt transaction leaving the previous-generation file uncleaned; disk-full during commit cleanup; concurrent install/migration racing the sweep.
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
- cannot retire leftover capsule authority while pending trans
- cannot remove capsule authority while an install transaction
- installed authority receipt does not match capsule '{capsule
- leftover capsule authority receipt is not a regular file: {}
- durable capsule {id} metadata executable hash differs from a
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/b8b73f310bfb6721.
Report an issue: GitHub.