{"record":{"id":"90f7c639e4871628","repo":"astrid-runtime/astrid","slug":"capsule-id-disappeared-during-introspection","errorCode":null,"errorMessage":"capsule {id} disappeared during introspection","messagePattern":"capsule (.+?) disappeared during introspection","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-capsule-install/src/principal_introspection.rs","lineNumber":46,"sourceCode":"///\n/// # Errors\n///\n/// Returns an error when the owner content graph is unavailable, a reserved\n/// package path is malformed, or a package disappears during readback.\npub fn list_durable_capsule_packages(\n    store: &Arc<RuntimePrincipalStore>,\n    uid: PrincipalUid,\n) -> anyhow::Result<Vec<DurableCapsuleIntrospection>> {\n    let owner = StateOwner::Principal(uid);\n    let registry = store.capsules();\n    registry\n        .list(&owner)?\n        .into_iter()\n        .map(|summary| {\n            let id = summary.id().to_owned();\n            let snapshot = registry\n                .get_snapshot(&owner, &id)?\n                .ok_or_else(|| anyhow::anyhow!(\"capsule {id} disappeared during introspection\"))?;\n            Ok(DurableCapsuleIntrospection { id, snapshot })\n        })\n        .collect()\n}\n\n/// Read one installed package by immutable UID and canonical identifier.\n///\n/// # Errors\n///\n/// Returns an error when the identifier is invalid, the package is absent or\n/// malformed, or the owner content graph cannot be verified.\npub fn read_durable_capsule_package(\n    store: &Arc<RuntimePrincipalStore>,\n    uid: PrincipalUid,\n    id: &str,\n) -> anyhow::Result<DurableCapsuleIntrospection> {\n    let owner = StateOwner::Principal(uid);\n    let snapshot = store","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-capsule-install/src/principal_introspection.rs#L28-L64","documentation":"list_durable_capsule_packages lists capsule summaries for an owner, then fetches each one's full snapshot via registry.get_snapshot. A None snapshot for an ID present in the listing means the capsule disappeared between the two calls; the function raises instead of returning a partial list.","triggerScenarios":"Iterating installed capsules for introspection while a concurrent install/remove/publish mutates the registry, so get_snapshot returns None for a listed ID.","commonSituations":"Running `capsule list`/introspection tooling at the same time as an install or uninstall in another shell; CI jobs sharing a capsule store without isolation; crashed removal leaving listing entries without snapshots.","solutions":["Re-run the introspection after concurrent operations finish.","Serialize registry mutations and introspection with a lock or per-user store isolation.","Check for orphaned entries (listed but unreadable) and clean/repair the registry store.","If persistent, republish or reinstall the affected capsule to restore its snapshot."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match list_durable_capsule_packages(&registry, &owner) {\n    Err(e) if e.to_string().contains(\"disappeared during introspection\") => {\n        // concurrent mutation: retry once after a short delay\n        std::thread::sleep(std::time::Duration::from_millis(250));\n        list_durable_capsule_packages(&registry, &owner)?\n    }\n    other => other?,\n}","preventionTips":["Avoid running installs/uninstalls concurrently with listing/introspection.","Snapshot the registry under a lock if you need a consistent view.","Clean orphaned listing entries after crashed operations."],"tags":["race-condition","introspection","registry"],"backgroundTag":"resource-not-found","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"}