astrid-runtime/astrid · error
system-resident capsule
Error message
system-resident capsule '{id}' must be created by the operator/default view before dependents attach What it means
A system-resident capsule's runtime is shared and must be created once by the operator/default view before any other principal can attach to it. If a non-default principal attempts to load the capsule and no existing system runtime is registered, the kernel rejects the load so the operator bootstraps it first.
Solutions
- Load the capsule once with the default principal (operator view) to create the system runtime.
- Order startup so the operator/default view loads system capsules before principal views attach.
- Remove the capsule from `system_capsules` if it is actually meant to be principal-scoped.
Example fix
// before kernel.load_capsule(&dir, &user_principal).await?; // after kernel.load_capsule(&dir, &PrincipalId::default()).await?; // bootstrap system runtime kernel.load_capsule(&dir, &user_principal).await?;
Defensive patterns
Strategy: validation
Validate before calling
if is_system_capsule(id) && principal != PrincipalId::default() && !daemon_has_system_runtime(id) {
return Err(anyhow!("bootstrap {id} via the default view first"));
} Try / catch
match kernel.load_capsule(&dir, &principal).await {
Err(e) if e.to_string().contains("must be created by the operator/default view") => {
kernel.load_capsule(&dir, &PrincipalId::default()).await?;
kernel.load_capsule(&dir, &principal).await
}
other => other,
} Prevention
- Load all system capsules with the default principal during daemon startup.
- Gate principal view loading on system-runtime readiness events.
- Document bootstrap order for system-resident services.
When it happens
Trigger: Loading a system-resident capsule with `principal != PrincipalId::default()` when the registry has no matching system runtime for that capsule id and WASM hash (i.e., the default view has never loaded it in this daemon).
Common situations: A principal's startup script loads a system capsule before the daemon has booted it; the daemon restarted and only non-default principals reattached; a new capsule version was installed but only principals reloaded it.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- cannot load capsule ' ' for retiring principal
- cannot reload capsule
- cannot replace capsule
- system-resident capsule
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/cc7c1f53400bd9a9.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-kernel/src/lib.rs:1761
// fresh runtime for its immutable UID; only an explicitly classified
// SystemResident service may attach another view to one runtime.
{
let mut registry = self.capsules.write().await;
if registry.get_for(principal, &id).is_some() {
return Ok(());
}
if system_runtime && registry.contains_system_runtime(&id, &wasm_hash) {
registry
.register_existing(&id, &wasm_hash, principal)
.map_err(|e| anyhow::anyhow!("Failed to add capsule view: {e}"))?;
if let Some(capsule) = registry.get_for(principal, &id) {
capsule.resume_for(principal);
}
return Ok(());
}
}
if system_runtime && principal != &PrincipalId::default() {
anyhow::bail!(
"system-resident capsule '{id}' must be created by the operator/default view before dependents attach"
);
}
// System residency is an operator/admin classification, not a host
// path ancestry claim. The source directory is a disposable
// materialization of the durable package registry; `system_capsules`
// is the authenticated admission set and the installed authority
// receipt was verified above.
let principal_uid = self.runtime_principal_uid(system_runtime, principal, &id)?;
let scope = principal_uid.map_or(
astrid_capsule::registry::RuntimeScope::SystemResident,
astrid_capsule::registry::RuntimeScope::Principal,
);
let runtime_id =
self.capsules
.write()
.awaitView on GitHub (pinned to affd8760f4)