astrid-runtime/astrid · error

capsule ' ' was not found in the install directories or…

Error message

capsule '{id}' was not found in the install directories or failed to load

What it means

Raised after an attempted on-demand load when the capsule is still absent from the registry (lib.rs:3111). Either no directory matching `id` was found in the principal's install directories, or the load was attempted and the capsule still failed to register. It is the definitive 'capsule unavailable' error for the resolve path.

Solutions

  1. Verify the capsule is installed in the principal's install directories and that the id matches the manifest `package.name` exactly
  2. Check the install-directory configuration/env so the kernel scans the correct location
  3. If the capsule exists but fails to load, look for the preceding 'capsule ... failed to load' error for the root cause
  4. Install the capsule for the principal before invoking it

Example fix

// before
kernel.invoke_capsule(&principal, "my-capsule", input).await?; // Err: not found in install dirs
// after
if !kernel.capsule_installed(&principal, "my-capsule") {
    kernel.install_capsule(&principal, capsule_package).await?;
}
kernel.invoke_capsule(&principal, "my-capsule", input).await?;
Defensive patterns

Strategy: try-catch

Validate before calling

let installed = install_dirs_for(principal)
    .iter()
    .any(|d| manifest_name(d) == id);
if !installed { /* install the capsule before invoking */ }

Try / catch

match kernel.invoke_capsule(principal, id, input).await {
    Err(e) if e.to_string().contains("was not found in the install directories") => {
        // distinguish 'not installed' from 'failed to load' via the preceding error
        return Err(user_facing_not_found(id));
    },
    other => other?,
}

Prevention

When it happens

Trigger: Invoking or restarting a capsule `id` for a `principal` where (a) no install directory contains a manifest whose `package.name` matches the id, or (b) the load ran but `registry.get_for(principal, id)` still returns `None` afterwards (lib.rs:3111).

Common situations: Typos in capsule ids or querying under the wrong principal; capsule never installed for that principal; install directory misconfigured (wrong ASTRID install path/env); load attempts that fail silently leave the registry empty and surface as this error.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/16c260f0dce79031. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-kernel/src/lib.rs:3111

            }
            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 next
    /// fan-out. Backs [`astrid_core::kernel_api::KernelRequest::UnloadCapsule`].
    ///
    /// Returns `Ok(true)` if the capsule was loaded and is now unregistered, or

View on GitHub (pinned to affd8760f4)