astrid-runtime/astrid · error

capsule source disappeared while preparing replacement: {}

Error message

capsule source disappeared while preparing replacement: {}

What it means

After preparing the replacement runtime, the kernel verifies that the Capsule.toml still exists at the expected manifest path. If the source materialization vanished mid-preparation (e.g., a concurrent cleanup or build process removed it), it aborts the replacement rather than activating an incomplete runtime.

Source

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

                &bound.snapshot,
            )?;
        }
        let principal_uid = self.runtime_principal_uid(system_runtime, principal, id)?;
        let runtime_id =
            self.capsules
                .write()
                .await
                .reserve_runtime_id(id.clone(), artifact, actual_scope)?;
        let mut capsule = self
            .build_capsule_runtime(
                manifest,
                &runtime_dir,
                (!system_runtime).then_some(principal),
                runtime_id.clone(),
            )
            .await?;
        if !manifest_path.exists() {
            anyhow::bail!(
                "capsule source disappeared while preparing replacement: {}",
                manifest_path.display()
            );
        }
        if let Err(error) = activate_and_wait_ready(id, capsule.as_mut()).await {
            capsule.request_cancel();
            if let Err(cleanup) = capsule.unload().await {
                tracing::warn!(capsule_id = %id, error = %cleanup, "Failed to unload rejected replacement candidate");
            }
            return Err(error);
        }
        Ok(PreparedRuntimeReplacement {
            capsule,
            runtime_id,
            principal_uid,
            system_runtime,
        })
    }

View on GitHub (pinned to affd8760f4)

Solutions

  1. Re-materialize the source directory and retry the replacement.
  2. Ensure no concurrent process deletes the workspace/runtime directory during replacement.
  3. Hold the capsule view/load lock around your replacement orchestration to serialize operations.

Example fix

// before
let prepared = kernel.prepare_replacement(id, &source_dir).await?;
activate(prepared).await?; // source may vanish in between
// after
if !source_dir.join("Capsule.toml").exists() {
    rematerialize_source(&source_dir)?; // restore before replacing
}
let prepared = kernel.prepare_replacement(id, &source_dir).await?;
activate(prepared).await?;
Defensive patterns

Strategy: retry

Validate before calling

let manifest_path = source_dir.join("Capsule.toml");
if !manifest_path.exists() {
    return Err(anyhow!("source not ready: {}", manifest_path.display()));
}

Try / catch

for attempt in 0..3 {
    match kernel.replace_runtime(id, &source_dir).await {
        Err(e) if e.to_string().contains("source disappeared") => {
            rematerialize_source(&source_dir)?;
            continue;
        }
        other => break other,
    }
}

Prevention

When it happens

Trigger: Live replacement where the source/runtime directory (or its Capsule.toml) is deleted between preparation and activation — typically a concurrent workspace clean, temp-dir reclamation, or another replace operation overwriting the directory.

Common situations: A build watcher cleans the runtime directory during a hot reload; two replacement jobs race on the same capsule; the source_dir points at a disposable temp path that garbage collection removes.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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