astrid-runtime/astrid · error
read durable capsule package '{id}': {error}
Error message
read durable capsule package '{id}': {error} What it means
Thrown in `remove_one_capsule` when `store.capsules().get_snapshot(&owner, id)` returns an `Err`. This is a read failure against the durable capsule registry — the snapshot lookup that must succeed before unload/delete could not be performed, so removal aborts before touching the live runtime.
Source
Thrown at crates/astrid-kernel/src/lib.rs:3261
#[cfg(not(target_family = "wasm"))]
pub(crate) async fn remove_one_capsule(
&self,
id: &astrid_capsule_types::CapsuleId,
principal: &PrincipalId,
) -> Result<bool, anyhow::Error> {
let store = self
.principal_store
.clone()
.ok_or_else(|| anyhow::anyhow!("authoritative principal store is unavailable"))?;
let uid = self
.principal_directory
.uid_for(principal)
.map_err(|error| anyhow::anyhow!("resolve durable owner for {principal}: {error}"))?;
let owner = astrid_storage::StateOwner::Principal(uid);
let snapshot = store
.capsules()
.get_snapshot(&owner, id.as_str())
.map_err(|error| anyhow::anyhow!("read durable capsule package '{id}': {error}"))?;
if snapshot.is_none() {
return Ok(false);
}
// Quiesce and unload before deleting the durable package. If unload
// fails, the package remains authoritative and can be retried on the
// next request; no live runtime is left without its registry source.
let _ = self.unload_one_capsule(id, principal).await?;
let removed = match store.capsules().remove(&owner, id.as_str()) {
Ok(removed) => removed,
Err(error) => {
self.ensure_principal_loaded(principal).await;
return Err(anyhow::anyhow!(
"remove durable capsule package '{id}': {error}"
));
},
};
if !removed {
// A concurrent administrative writer won the generation race. TheView on GitHub (pinned to affd8760f4)
Solutions
- Inspect the wrapped source error for the storage backend root cause (I/O, permissions, corruption).
- Check storage backend health and disk space; retry the removal after restoring service.
- If the record is corrupt, repair or clear the durable capsule package with storage-level tooling, then retry.
Example fix
// before: blind retry loop
loop { kernel.remove_one_capsule(&id, &principal).await?; }
// after: inspect cause, back off on transient backend errors
match kernel.remove_one_capsule(&id, &principal).await {
Ok(_) => {},
Err(e) if is_transient(&e) => tokio::time::sleep(BACKOFF).await,
Err(e) => return Err(e),
} Defensive patterns
Strategy: retry
Validate before calling
fn store_reachable(store: &Store) -> bool { store.health_check().is_ok() } Try / catch
match kernel.remove_one_capsule(&id, &principal).await {
Err(e) if is_transient(&e) && attempts < 3 => {
tokio::time::sleep(backoff).await; // retry
},
other => other?,
} Prevention
- Monitor disk space and storage backend health.
- Avoid restarting storage services during admin windows.
- Test crash recovery so partially-written capsule packages are detected.
When it happens
Trigger: The underlying storage backend errors while reading the capsule record: corrupted store, I/O failure, lock contention, backend unreachable, or a serialization error decoding the snapshot record for `{owner}/{id}`.
Common situations: Disk full or failing on the storage volume; a partially-written capsule package from a crash; storage service restart during an admin delete; schema change making an old snapshot record undecodable.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- audit read failed: {e}
- authoritative principal store is unavailable
- resolve durable owner for {principal}: {error}
- remove durable capsule package '{id}': {error}
- unexpected response from kernel: {other:?}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/37482a5104ef6eae.
Report an issue: GitHub.