astrid-runtime/astrid · error
capsule {operation} '{}' is outside the explicit workspace p
Error message
capsule {operation} '{}' is outside the explicit workspace portal and has no durable registry authority What it means
capture_bound_materialization first tries to bind the capsule to a durable registry publication (published_capsule_snapshot + repair) and then falls back to verifying the directory's installed authority. If neither applies — the registry verification fails AND a durable principal store exists but the target directory lies outside the explicit workspace state dir — the kernel refuses the operation: the capsule would run from an arbitrary path with no durable authority backing it, bypassing the workspace portal.
Source
Thrown at crates/astrid-kernel/src/capsule_materialization.rs:141
if let Some(snapshot) = snapshot {
let runtime_dir = self.published_cache_target(principal, manifest, &snapshot)?;
let bound_manifest = self.repair_published_materialization(
&runtime_dir,
principal,
manifest,
&snapshot,
)?;
return Ok(Some(BoundMaterialization {
snapshot,
runtime_dir,
manifest: bound_manifest,
}));
}
if !self.verify_registry_materialization(dir, principal, manifest)? {
if self.principal_store.is_some()
&& !dir.starts_with(self.workspace_selection.state_dir())
{
anyhow::bail!(
"capsule {operation} '{}' is outside the explicit workspace portal and \
has no durable registry authority",
manifest.package.name
);
}
self.verify_installed_authority_for_runtime(dir, manifest).map_err(|error| {
anyhow::anyhow!(
"capsule {operation} '{}' exceeds or cannot prove its installed authority: {error:#}",
manifest.package.name
)
})?;
}
Ok(None)
}
/// Repair a stale or missing cache generation from one exact snapshot.
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
pub(crate) fn ensure_published_materialization(View on GitHub (pinned to affd8760f4)
Solutions
- Load the capsule from inside the explicit workspace portal (a path under workspace_selection.state_dir()) or install/publish it into the durable registry so verify_registry_materialization succeeds.
- Publish the capsule (register its snapshot and authority with the principal store) before attempting load_capsule/prepare_runtime_replacement on that path.
- Verify the workspace state_dir configuration matches where the capsule is actually materialized; a path-prefix mismatch alone triggers this bail.
- If a locally built capsule must run, route it through the workspace portal directory (copy/materialize it under state_dir) rather than passing its build path directly.
Example fix
// before: loading a capsule from an arbitrary path
let manifest = kernel.load_capsule(Path::new("/tmp/build/my-capsule"), &principal)?;
// after: load from inside the workspace portal state dir
let portal_dir = kernel.workspace_selection.state_dir().join("my-capsule");
let manifest = kernel.load_capsule(&portal_dir, &principal)?; Defensive patterns
Strategy: validation
Validate before calling
// Confirm the capsule lives in the workspace portal before loading
let state_dir = kernel.workspace_selection.state_dir();
let dir = std::fs::canonicalize(&dir)?;
let state_dir = std::fs::canonicalize(state_dir)?;
if !dir.starts_with(state_dir) {
anyhow::bail!("capsule must be published or placed under the workspace state dir");
} Type guard
fn inside_workspace(dir: &Path, state_dir: &Path) -> bool {
match (std::fs::canonicalize(dir), std::fs::canonicalize(state_dir)) {
(Ok(d), Ok(s)) => d.starts_with(s),
_ => false,
}
} Try / catch
match kernel.load_capsule(&dir, &principal) {
Err(e) if e.to_string().contains("outside the explicit workspace portal") => {
publish_to_registry(&manifest)?; // or move capsule under state_dir
kernel.load_capsule(&dir, &principal)
}
other => other,
} Prevention
- Always publish capsules to the durable registry before loading them by path.
- Configure the workspace state_dir to exactly match the installation root.
- Never point loaders at build-output or scratch directories when a principal store is active.
- Re-install capsules created before the durable registry was enabled.
When it happens
Trigger: load_capsule or prepare_runtime_replacement is called with a `dir` such that published_capsule_snapshot finds no publication, verify_registry_materialization returns false, self.principal_store is Some, and dir does not start with self.workspace_selection.state_dir() — e.g. loading a capsule from /tmp/my-capsule or another project folder while a durable registry is configured.
Common situations: A developer points the loader at a local checkout/build-output directory instead of an installed or workspace-portal capsule; the workspace state dir is misconfigured (different path than where capsules were installed); a capsule was installed before the durable principal store was enabled and now lives outside the portal; CI copies capsule directories to scratch paths outside the workspace.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- capsule '{}' changed after authority review (approved {}, fo
- {label} is not a canonical cache component
- materialized capsule manifest exceeds durable authority appr
- capsule materialization target is redirected or not a direct
- stale mount recovery belongs to another acting principal
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/1d527fb62b4100c3.
Report an issue: GitHub.