astrid-runtime/astrid · error
live replacement of stdio MCP capsule
Error message
live replacement of stdio MCP capsule '{id}' is not yet atomic; restart the daemon to activate these process changes What it means
Live (in-place) replacement cannot atomically swap out stdio MCP server child processes; restarting the daemon is required to apply manifest changes that affect MCP processes. The kernel deliberately refuses rather than performing a partially-applied, non-atomic update.
Solutions
- Restart the daemon so the new capsule (with its MCP processes) activates cleanly.
- Unload and reload the capsule instead of live replacement.
- If no MCP change is intended, revert the `mcp_servers` section before replacing.
Example fix
// before kernel.prepare_runtime_replacement(id, source_dir).await?; // fails: has mcp_servers // after daemon.restart().await?; // applies mcp_servers changes atomically
Defensive patterns
Strategy: validation
Validate before calling
let manifest = astrid_capsule::discovery::load_manifest(&runtime_dir.join("Capsule.toml"))?;
if !manifest.mcp_servers.is_empty() {
return Err(anyhow!("mcp_servers present; full daemon restart required"));
} Try / catch
match kernel.replace_runtime(id, &source_dir).await {
Err(e) if e.to_string().contains("not yet atomic") => daemon.restart().await,
other => other,
} Prevention
- Treat mcp_servers changes as restart-required deployments.
- Split MCP servers into separate capsules to keep core capsules hot-reloadable.
- Detect mcp_servers diffs in CI and schedule restarts.
When it happens
Trigger: Invoking the live replacement API on a capsule whose (bound) manifest still declares one or more `mcp_servers` entries.
Common situations: Hot-reloading a capsule during development after adding or editing MCP server definitions; CI applying manifest updates to a running daemon with MCP servers.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- cannot replace capsule
- capsule ' ': branch/rev require building from source and…
- capsule ' ' cannot change runtime scope during live…
- capsule source disappeared while preparing replacement
- legacy principal retains unsupported state; no…
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/9da79ae6af017fd7.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-kernel/src/lib.rs:2027
);
}
let bound = self.capture_bound_materialization(
source_dir,
principal,
&manifest,
"replacement source",
)?;
let runtime_dir = bound.as_ref().map_or_else(
|| source_dir.to_path_buf(),
|bound| bound.runtime_dir.clone(),
);
let manifest = bound
.as_ref()
.map_or_else(|| manifest, |bound| bound.manifest.clone());
let manifest_path = runtime_dir.join("Capsule.toml");
self.verify_workspace_component_paths(&runtime_dir, &manifest)?;
if !manifest.mcp_servers.is_empty() {
anyhow::bail!(
"live replacement of stdio MCP capsule '{id}' is not yet atomic; restart the daemon to activate these process changes"
);
}
let artifact = capsule_instance_hash(&manifest, &runtime_dir);
let system_allowed = self.system_capsules.read().await.contains(id.as_str());
let system_runtime = classify_runtime_residency(&manifest, id, system_allowed)?.is_system();
if system_runtime && !manifest.mcp_servers.is_empty() {
anyhow::bail!(
"system-resident capsule '{id}' cannot host principal-bearing stdio MCP servers"
);
}
// Replacement authority is the authenticated operator classification
// and installed receipt, never the ancestry of `source_dir`.
let actual_scope = if system_runtime {
astrid_capsule::registry::RuntimeScope::SystemResident
} else {
astrid_capsule::registry::RuntimeScope::Principal(
self.principal_directory.uid_for(principal)?,View on GitHub (pinned to affd8760f4)