astrid-runtime/astrid · error
capsule ' ' failed to load
Error message
capsule '{id}' failed to load: {error:#} What it means
Wrapper error raised when on-demand loading of a capsule from its install directory fails (lib.rs:3108). The kernel found a matching manifest for `id` in the principal's sorted install directories, attempted `load_capsule`, and the underlying load error (compilation, manifest validation, I/O) is chained as `{error:#}`. The original cause is preserved, so read the chained message for the real failure.
Solutions
- Read the chained `{error:#}` cause to identify the actual load failure and fix that root problem
- Validate the capsule's manifest and source in its install directory (fix syntax, missing files, or schema issues)
- Reinstall/redeploy the capsule from a known-good package
- Check filesystem permissions on the capsule's install directory
Example fix
// Diagnose the wrapped cause instead of treating it as not-found
match kernel.ensure_capsule_loaded(&principal, &id).await {
Err(e) if e.to_string().contains("failed to load") => {
// inspect source(&e) for the real compile/manifest error
tracing::error!("load failure root cause: {:#}", e);
},
_ => {},
} Defensive patterns
Strategy: try-catch
Validate before calling
let loadable = capsule_manifest_parses(&install_dir)?
&& required_source_files_present(&install_dir)?; Try / catch
match kernel.ensure_capsule_loaded(principal, id).await {
Err(e) if e.to_string().contains("failed to load") => {
let root = e.root_cause(); // surface the chained cause to the operator
tracing::error!("capsule load root cause: {root}");
},
other => other?,
} Prevention
- Validate capsule manifests and compile capsules in CI before deployment
- Keep capsule SDK versions in sync between build and kernel
- Check install-directory permissions after deploys
When it happens
Trigger: Lazily resolving a capsule id during an operation (invoke/restart-style path): a directory matching the id exists under the principal's install dirs, `load_capsule(dir, principal)` returns `Err`, and the error is wrapped at lib.rs:3108.
Common situations: Capsule source on disk fails to compile or validate (bad manifest, missing files, syntax errors) after a deploy or manual edit; permission problems reading the install directory; loading a capsule built against an incompatible capsule SDK version.
Related errors
- an incomplete capsule authority update exists at
- cannot load capsule ' ' for unadmitted principal
- cannot remove capsule authority while an install…
- capsule ' ' has no source directory
- capsule ' ' not found in registry
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/019e72a223634001.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-kernel/src/lib.rs:3108
if registered {
if self.capabilities.is_principal_retiring(principal).await {
anyhow::bail!("cannot reload capsule '{id}' for retiring principal '{principal}'");
}
self.restart_capsule(id, principal, None).await?;
self.publish_capsules_loaded().await;
} else {
drop(view_guard);
// Build or refresh this principal's view from its installed set.
self.ensure_principal_loaded(principal).await;
if self.capsules.read().await.get_for(principal, id).is_none()
&& let Some((_, dir)) = self
.sorted_principal_capsules(principal)
.into_iter()
.find(|(manifest, _)| manifest.package.name == id.as_str())
{
self.load_capsule(dir, principal)
.await
.map_err(|error| anyhow::anyhow!("capsule '{id}' failed to load: {error:#}"))?;
}
if self.capsules.read().await.get_for(principal, id).is_none() {
return Err(anyhow::anyhow!(
"capsule '{id}' was not found in the install directories or failed to load"
));
}
self.publish_capsules_loaded().await;
}
Ok(())
}
/// Unload a single capsule by id without a daemon restart.
///
/// Mirrors the unregister half of [`Self::restart_capsule`]: it removes the
/// capsule from the running registry and explicitly unloads it (there is no
/// async `Drop`, so we must do it here to avoid leaking MCP subprocesses and
/// other engine resources), then publishes `astrid.v1.capsules_loaded` so the
/// tool surface refreshes — the departed capsule self-excludes from the nextView on GitHub (pinned to affd8760f4)