astrid-runtime/astrid · error
capsule {} disappeared during durable scan
Error message
capsule {} disappeared during durable scan What it means
scan_durable_capsules lists a principal's capsules from the durable registry and then fetches a full snapshot for each summary. If the snapshot lookup returns None for a summary that the same registry just listed, the registry is internally inconsistent (the entry vanished between list and get_snapshot), and the scan bails with this message rather than silently dropping the capsule.
Source
Thrown at crates/astrid-capsule-install/src/meta.rs:158
pub meta: Option<CapsuleMeta>,
/// Where this capsule was found.
pub location: CapsuleLocation,
}
/// Enumerate authoritative packages for one owner-root content projection.
///
/// This is the steady-state discovery API. It never scans native home or
/// workspace capsule directories; those paths are migration/cache inputs only.
pub fn scan_durable_capsules(
store: &RuntimePrincipalStore,
owner: &StateOwner,
location: CapsuleLocation,
) -> anyhow::Result<Vec<InstalledCapsule>> {
let registry = store.capsules();
let mut capsules = Vec::new();
for summary in registry.list(owner)? {
let Some(snapshot) = registry.get_snapshot(owner, summary.id())? else {
anyhow::bail!("capsule {} disappeared during durable scan", summary.id());
};
let meta = serde_json::from_slice(&snapshot.package().metadata)
.with_context(|| format!("decode durable metadata for capsule {}", summary.id()))?;
capsules.push(InstalledCapsule {
name: summary.id().to_owned(),
meta: Some(meta),
location,
});
}
capsules.sort_by(|left, right| left.name.cmp(&right.name));
Ok(capsules)
}
/// Scan user-level and workspace capsule directories, returning all installed
/// capsules sorted alphabetically by name.
pub fn scan_installed_capsules() -> anyhow::Result<Vec<InstalledCapsule>> {
scan_installed_capsules_with_layout(&WorkspaceLayout::default())
}View on GitHub (pinned to affd8760f4)
Solutions
- Re-run the scan; a transient concurrent delete may succeed on the second pass
- Stop concurrent writers (other capsule installs/removes) during the scan
- Inspect the principal store for orphaned summary entries and repair/remove them
- If caused by external cleanup, restore capsule snapshots from backup or reinstall the capsule
Defensive patterns
Strategy: retry
Try / catch
let capsules = loop {
match scan_durable_capsules(&store, owner, location).await {
Ok(c) => break c,
Err(e) if e.to_string().contains("disappeared during durable scan") && retries < 3 => { retries += 1; continue; }
Err(e) => return Err(e),
}
}; Prevention
- Serialize capsule mutations (install/remove) with scans via a lock or the kernel
- Avoid external tools deleting files under the principal store while scans run
- Regularly audit the store for orphaned summary entries without snapshots
- Use store-level transactions for remove so list/get_snapshot stay consistent
When it happens
Trigger: Concurrent deletion of a capsule (e.g. another process/thread calling remove on the RuntimePrincipalStore) between registry.list(owner) and registry.get_snapshot(owner, id); a corrupted or pruned store where snapshots were removed but summary index entries remain.
Common situations: Two tools managing capsules on the same principal concurrently; a crash or manual store cleanup that removed snapshot data but left summaries; filesystem-level deletion under the store while a scan runs.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- capsule {} disappeared during durable contracts scan
- legacy capsule {id} changed before retirement
- legacy capsule {id} metadata changed before retirement
- shutdown stage gateway.startup_identity: startup generation
- cannot load capsule '{id}' for retiring principal '{principa
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/9839c8cb076e2f96.
Report an issue: GitHub.