{"record":{"id":"74f7d14f0a6d121a","repo":"astrid-runtime/astrid","slug":"durable-capsule-package-id-disappeared-during","errorCode":null,"errorMessage":"durable capsule package '{id}' disappeared during removal","messagePattern":"durable capsule package '(.+?)' disappeared during removal","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/astrid-kernel/src/lib.rs","lineNumber":3283,"sourceCode":"        // Quiesce and unload before deleting the durable package. If unload\n        // fails, the package remains authoritative and can be retried on the\n        // next request; no live runtime is left without its registry source.\n        let _ = self.unload_one_capsule(id, principal).await?;\n        let removed = match store.capsules().remove(&owner, id.as_str()) {\n            Ok(removed) => removed,\n            Err(error) => {\n                self.ensure_principal_loaded(principal).await;\n                return Err(anyhow::anyhow!(\n                    \"remove durable capsule package '{id}': {error}\"\n                ));\n            },\n        };\n        if !removed {\n            // A concurrent administrative writer won the generation race. The\n            // durable package is still authoritative; restore the just-closed\n            // runtime view before surfacing the conflict.\n            self.ensure_principal_loaded(principal).await;\n            return Err(anyhow::anyhow!(\n                \"durable capsule package '{id}' disappeared during removal\"\n            ));\n        }\n        Ok(true)\n    }\n\n    #[cfg(target_family = \"wasm\")]\n    pub(crate) async fn remove_one_capsule(\n        &self,\n        _id: &astrid_capsule_types::CapsuleId,\n        _principal: &PrincipalId,\n    ) -> Result<bool, anyhow::Error> {\n        Err(anyhow::anyhow!(\n            \"durable capsule removal is unavailable on portable hosts\"\n        ))\n    }\n\n    /// Remove every capsule view owned by `principal` before that principal's","sourceCodeStart":3265,"sourceCodeEnd":3301,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/lib.rs#L3265-L3301","documentation":"Thrown in `remove_one_capsule` when `store.capsules().remove` returns `Ok(false)` — the package existed at snapshot time but was gone (or generation-superseded) at delete time. A concurrent administrative writer won the generation race; the kernel restores the just-closed runtime view via `ensure_principal_loaded` and surfaces this conflict instead of silently reporting success.","triggerScenarios":"Two concurrent removals (or a removal racing another writer) on the same capsule package: the first delete commits, the second's conditional remove finds nothing to delete and returns `false`.","commonSituations":"Double-clicked/duplicated delete requests from an admin UI; two operators deleting the same capsule simultaneously; a retried request arriving after the first already succeeded.","solutions":["Treat this as a lost race: re-read the capsule state; if it is genuinely gone, report success to the user (idempotent delete).","Retry the operation only after confirming the package exists again.","Serialize concurrent administrative deletes per capsule/principal to prevent the race."],"exampleFix":"// before: treat false as hard failure\nkernel.remove_one_capsule(&id, &principal).await?;\n// after: idempotent handling\nmatch kernel.remove_one_capsule(&id, &principal).await {\n    Ok(_) => {},\n    Err(e) if e.to_string().contains(\"disappeared during removal\") => {\n        // someone else already deleted it; treat as success\n    },\n    Err(e) => return Err(e),\n}","handlingStrategy":"try-catch","validationCode":"fn capsule_still_exists(kernel: &Kernel, id: &CapsuleId, p: &PrincipalId) -> bool { kernel.capsule_exists(id, p) }","typeGuard":null,"tryCatchPattern":"match kernel.remove_one_capsule(&id, &principal).await {\n    Ok(_) => {},\n    Err(e) if e.to_string().contains(\"disappeared during removal\") => {\n        // lost generation race; verify state and treat as idempotent success\n        if !kernel.capsule_exists(&id, &principal) { info!(\"already deleted\"); }\n    },\n    Err(e) => return Err(e),\n}","preventionTips":["Make delete operations idempotent in the caller.","Use per-capsule locks or a single admin queue to avoid concurrent writers.","Debounce duplicate delete requests in admin UIs."],"tags":["rust","concurrency","storage","race-condition"],"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"}