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

  1. Load the capsule once with the default principal (operator view) to create the system runtime.
  2. Order startup so the operator/default view loads system capsules before principal views attach.
  3. 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

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


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()
                .await

View on GitHub (pinned to affd8760f4)