astrid-runtime/astrid · error
authoritative principal store is unavailable
Error message
authoritative principal store is unavailable
What it means
Thrown in `remove_one_capsule` when the kernel's `principal_store` field is `None`. The principal store is the authoritative durable registry of capsule packages; without it the kernel cannot read or delete durable state, so removal is refused instead of operating on a stale or in-memory-only view. This is a startup/initialization invariant: the store should be attached before any capsule administration is attempted.
Source
Thrown at crates/astrid-kernel/src/lib.rs:3252
/// Atomically remove one capsule package from the authenticated owner's
/// durable registry, then tear down the corresponding live view. Native
/// install directories are never consulted or deleted by this path.
///
/// # Errors
///
/// Returns an error when the durable store or owner mapping is unavailable,
/// the registry mutation fails, or the live view cannot be unloaded.
#[cfg(not(target_family = "wasm"))]
pub(crate) async fn remove_one_capsule(
&self,
id: &astrid_capsule_types::CapsuleId,
principal: &PrincipalId,
) -> Result<bool, anyhow::Error> {
let store = self
.principal_store
.clone()
.ok_or_else(|| anyhow::anyhow!("authoritative principal store is unavailable"))?;
let uid = self
.principal_directory
.uid_for(principal)
.map_err(|error| anyhow::anyhow!("resolve durable owner for {principal}: {error}"))?;
let owner = astrid_storage::StateOwner::Principal(uid);
let snapshot = store
.capsules()
.get_snapshot(&owner, id.as_str())
.map_err(|error| anyhow::anyhow!("read durable capsule package '{id}': {error}"))?;
if snapshot.is_none() {
return Ok(false);
}
// Quiesce and unload before deleting the durable package. If unload
// fails, the package remains authoritative and can be retried on the
// next request; no live runtime is left without its registry source.
let _ = self.unload_one_capsule(id, principal).await?;
let removed = match store.capsules().remove(&owner, id.as_str()) {
Ok(removed) => removed,View on GitHub (pinned to affd8760f4)
Solutions
- Ensure the kernel is initialized with a durable principal store before accepting capsule removal requests (check the store-attach step for silent failures).
- Guard callers: check whether the durable store is configured before invoking `remove_one_capsule`.
- If running in an intentionally ephemeral mode, use in-memory unload (`unload_one_capsule`) instead of durable removal.
Example fix
// before: kernel built without store
let kernel = AstridKernel::builder().build()?;
kernel.remove_one_capsule(&id, &principal).await?;
// after
let kernel = AstridKernel::builder()
.with_principal_store(durable_store)
.build()?;
kernel.remove_one_capsule(&id, &principal).await?; Defensive patterns
Strategy: try-catch
Validate before calling
fn can_remove_durably(kernel: &Kernel) -> bool { kernel.has_principal_store() } Type guard
fn store_configured(kernel: &Kernel) -> bool { kernel.principal_store().is_some() } Try / catch
match kernel.remove_one_capsule(&id, &principal).await {
Ok(removed) => info!("removed={removed}"),
Err(e) if e.to_string().contains("principal store is unavailable") => {
warn!("durable store not configured; re-initialize kernel with storage");
},
Err(e) => return Err(e),
} Prevention
- Always construct the kernel through a builder/factory that attaches the principal store.
- Add an integration smoke test that exercises a durable removal on every startup path.
- Fail fast at startup if the durable store is required but absent.
When it happens
Trigger: Calling `remove_one_capsule` on a kernel instance constructed without a durable principal store (store attach failed, was skipped in an embedded/test configuration, or the kernel is running in a degraded mode where the store handle was never wired up).
Common situations: Embedding astrid-kernel in a harness or test that builds the kernel without persistent storage; a failed storage backend initialization silently leaving the store `None`; running a native build against a misconfigured storage path so store attachment never completes before an admin delete request arrives.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- resolve durable owner for {principal}: {error}
- read durable capsule package '{id}': {error}
- remove durable capsule package '{id}': {error}
- unexpected response from kernel: {other:?}
- unexpected {kind:?} in a canonical File owning closure
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/f7975b7b16522ab2.
Report an issue: GitHub.