{"record":{"id":"6ce17210853341ec","repo":"astrid-runtime/astrid","slug":"durable-capsule-removal-is-unavailable-on-portable","errorCode":null,"errorMessage":"durable capsule removal is unavailable on portable hosts","messagePattern":"durable capsule removal is unavailable on portable hosts","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/lib.rs","lineNumber":3296,"sourceCode":"        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\n    /// persistent state is reclaimed.\n    ///\n    /// The load lock closes the race with background warm/install discovery:\n    /// once the profile/identity fence has closed new authorization, no loader\n    /// can re-attach a view between the snapshot and the last unload. Each\n    /// release uses [`Self::unload_one_capsule`]. Principal runtimes are always\n    /// removed; dependent `SystemResident` views survive only while their\n    /// explicit owner remains installed.\n    pub(crate) async fn unload_principal_capsules(\n        &self,\n        principal: &PrincipalId,\n    ) -> Result<Vec<astrid_capsule_types::CapsuleId>, anyhow::Error> {\n        let mut ids: Vec<_> = {","sourceCodeStart":3278,"sourceCodeEnd":3314,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/lib.rs#L3278-L3314","documentation":"The WASM (`target_family = \"wasm\"`) stub of `remove_one_capsule` unconditionally returns this error. Durable capsule removal requires native filesystem-backed storage, which is not available on portable (WASM) hosts, so the operation is compiled out and always fails with this message.","triggerScenarios":"Any call to `remove_one_capsule` when the kernel is compiled for a WASM target (browser, in-process sandbox, portable runtime) — there is no code path that can succeed.","commonSituations":"Running the kernel embedded in a browser or WASM sandbox and attempting capsule uninstall/management; reusing native admin code unmodified on a portable host.","solutions":["Compile for a native target if durable removal is required.","On WASM, gate removal features out of the UI/API and surface 'not supported on this platform' to users.","Use an alternative removal mechanism provided by the host environment, or only unload in-memory on portable hosts."],"exampleFix":"// before\nkernel.remove_one_capsule(&id, &principal).await?;\n// after\n#[cfg(target_family = \"wasm\")]\nanyhow::bail!(\"capsule removal is not supported on portable hosts\");\n#[cfg(not(target_family = \"wasm\"))]\nkernel.remove_one_capsule(&id, &principal).await?;","handlingStrategy":"validation","validationCode":"#[cfg(target_family = \"wasm\")]\nfn durable_removal_supported() -> bool { false }\n#[cfg(not(target_family = \"wasm\"))]\nfn durable_removal_supported() -> bool { true }","typeGuard":"fn supports_durable_removal() -> bool {\n    cfg!(not(target_family = \"wasm\"))\n}","tryCatchPattern":"if cfg!(target_family = \"wasm\") {\n    return Err(anyhow!(\"capsule removal is not available on portable hosts\"));\n}\nkernel.remove_one_capsule(&id, &principal).await?;","preventionTips":["Feature-gate durable removal UI/API behind non-WASM targets.","Compile-time assertions in tests that portable builds do not expose removal.","Document platform capability differences for embedders."],"tags":["rust","wasm","unsupported-platform","kernel"],"backgroundTag":"unsupported-platform","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"}