astrid-runtime/astrid · error
durable capsule disappeared after publish
Error message
durable capsule {id} disappeared after publish What it means
publish_directory_package installs the package into the registry and then immediately re-reads it with read_verified_durable_package to confirm the publish landed. If the verification read returns None — the capsule is absent right after a successful install call — this error reports the post-publish inconsistency instead of silently succeeding.
Solutions
- Re-run the publish; transient races or temporary storage failures usually clear.
- Check that the owner/principal and uid passed to publish_directory_package match the scope you later read from.
- Inspect the registry store for the capsule (list by owner) to see whether the install actually landed.
- Rule out concurrent processes mutating the same store; serialize publish operations.
- If reproducible, check registry.install's write path/storage backend for silent failures and repair the store.
Defensive patterns
Strategy: retry
Try / catch
match publish_directory_package(/* ... */) {
Err(e) if e.to_string().contains("disappeared after publish") => {
// verify scope params, then retry once
std::thread::sleep(std::time::Duration::from_millis(250));
publish_directory_package(/* same args */)?
}
other => other?,
} Prevention
- Ensure owner/principal/uid arguments are consistent between install and verification.
- Serialize publish and remove operations against the same store.
- Check the storage backend for silent write failures or eventual-consistency semantics.
- List the registry after failures to confirm whether the package actually landed.
When it happens
Trigger: registry.install reports success but read_verified_durable_package(store, uid, id) cannot find the capsule: concurrent removal between install and read, the install silently writing to a different owner/uid scope than the read, or a corrupted/rolled-back store.
Common situations: Two processes publishing/removing the same capsule concurrently; mismatched principal/uid parameters between install and verification; storage backends with eventual consistency or failing writes that install did not surface.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- capsule disappeared during durable contracts scan
- legacy env/secret source changed before import
- cannot load capsule ' ' for retiring principal
- cannot reload capsule
- cannot replace capsule
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/7ca829cd6a19c36f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-capsule-install/src/storage.rs:486
.context("stage verified durable capsule package")?;
// Storage-backed installs initially assemble a lifecycle workspace that
// intentionally omits the WASM component. Replace it with the complete
// verified package before publication so an immediately triggered live
// reload sees the same bytes that a restart would rematerialize.
let previous_target = materialization.path().join("previous");
fs::rename(target_dir, &previous_target)
.context("stage incomplete capsule install cache for replacement")?;
if let Err(error) = fs::rename(&staged_target, target_dir) {
let _ = fs::rename(&previous_target, target_dir);
return Err(error).context("publish verified capsule materialization");
}
registry
.install(&owner, &id, &package, expected)
.with_context(|| format!("publish durable capsule package {id} for {principal}"))?;
read_verified_durable_package(store, uid, &id)?
.ok_or_else(|| anyhow::anyhow!("durable capsule {id} disappeared after publish"))?;
Ok(())
}
/// Publish a package when the caller already has canonical bytes.
///
/// This is used by archive migration and by tests that have no source
/// directory to materialize. The caller must provide the immutable principal
/// UID, so alias reuse cannot redirect the package to a different owner.
pub fn publish_package(
store: &Arc<RuntimePrincipalStore>,
uid: astrid_core::identity::PrincipalUid,
id: &str,
package: &CapsulePackage,
) -> anyhow::Result<()> {
let owner = StateOwner::Principal(uid);
let registry = store.capsules();
let expected = registry
.get_snapshot(&owner, id)?View on GitHub (pinned to affd8760f4)