astrid-runtime/astrid · error
ps failed while inspecting MCP processes
Error message
ps failed while inspecting MCP processes
What it means
gc() shells out to `ps -axo pid=,ppid=,command=` to enumerate processes for reaping orphaned MCP servers. If ps runs but exits non-zero, gc cannot enumerate processes and bails with this error. (Launch failure of ps itself produces the context-wrapped 'failed to inspect MCP processes with ps' error instead.)
Source
Thrown at crates/astrid-cli/src/commands/mcp/lifecycle.rs:905
.get(index)
.is_some_and(|token| matches!(command_file_name(token), "astrid" | "aos"))
}
fn is_reapable_mcp(command: &str) -> bool {
is_long_mcp_serve(command) || is_mcp_attach(command)
}
/// Remove orphaned long-timeout `mcp serve` and `mcp attach` processes.
///
/// Never signals Python `aos-mcp-frame` processes. Those abort on 3.14 if a
/// SIGKILL races `Buffered_close`; attach children are the reap target.
pub(crate) fn gc() -> Result<ExitCode> {
let output = Command::new("ps")
.args(["-axo", "pid=,ppid=,command="])
.output()
.context("failed to inspect MCP processes with ps")?;
if !output.status.success() {
anyhow::bail!("ps failed while inspecting MCP processes");
}
let listing = String::from_utf8_lossy(&output.stdout);
let mut reaped = 0_u32;
for row in listing.lines().filter_map(parse_process_row) {
if row.pid == std::process::id() || !is_reapable_mcp(&row.command) {
continue;
}
let parent_dead =
row.ppid == 1 || !crate::commands::daemon_control::is_process_alive(row.ppid);
if !parent_dead {
continue;
}
// Re-read the command immediately before signalling to avoid killing a
// recycled PID that no longer belongs to a reapable MCP shim.
if !process_command(row.pid).is_some_and(|command| is_reapable_mcp(&command)) {
continue;
}
#[cfg(unix)]View on GitHub (pinned to affd8760f4)
Solutions
- Verify `ps -axo pid=,ppid=,command=` runs successfully in your shell; fix or replace the failing ps.
- Install a full procps ps in the container image (e.g. `apt-get install procps` / Alpine `apk add procps`).
- Run astrid outside the sandbox/policy that blocks ps.
- Report the issue: gc could fall back to /proc scanning on Linux.
Example fix
// before (Alpine container) astrid mcp gc # -> ps failed while inspecting MCP processes // after apk add procps && astrid mcp gc
Defensive patterns
Strategy: fallback
Validate before calling
let check = std::process::Command::new("ps")
.args(["-axo", "pid=,ppid=,command="])
.output()?;
if !check.status.success() {
eprintln!("ps incompatible; install procps before running astrid mcp gc");
} Try / catch
if let Err(e) = astrid::mcp::gc() {
if e.to_string().contains("ps failed") {
eprintln!("install procps (apt-get install procps / apk add procps) or run on a host with full ps");
}
} Prevention
- Install procps in minimal container images
- Test `ps -axo pid=,ppid=,command=` works before automating gc
- Avoid shim/wrapper ps binaries on PATH in hardened environments
- Prefer standard Linux base images for astrid workloads
When it happens
Trigger: Running `astrid mcp gc` on a system where the `ps` binary exists but exits with failure — e.g. a restricted/incompatible ps (busybox variants lacking -axo), a broken /proc, or ps blocked by security policy.
Common situations: Minimal containers with busybox ps that rejects `-axo pid=,ppid=,command=`; hardened environments blocking ps via seccomp/AppArmor; corrupted PATH picking a shim ps that fails.
Related errors
- editor '{editor}' exited with non-zero status
- git could not inspect captured version: {}
- {name} not found. Ensure it is installed alongside the astri
- {name} is not installed beside the Astrid CLI; refusing a PA
- unexpected response from kernel: {other:?}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/960a25ba9eb2af82.
Report an issue: GitHub.