NousResearch/hermes-agent · error · anyhow::Error
waiting for child: {e}
Error message
waiting for child: {e} What it means
Raised in run_streamed when awaiting the already-spawned child's exit status fails (child.wait().await returned Err). The process ran and its output was streamed; only the final wait syscall failed — typically the child was killed by a signal (no exit code available) or reaped/killed externally (e.g. job-object teardown, system shutdown) so tokio cannot report a status.
Source
Thrown at apps/bootstrap-installer/src-tauri/src/update.rs:858
Ok(Some(l)) => emit_log(app, stage_owned.as_deref(), LogStream::Stdout, &l),
Ok(None) => break,
Err(e) => { tracing::warn!("stdout read error: {e}"); break; }
},
line = read_decoded_line(&mut err, &mut err_buf) => match line {
Ok(Some(l)) => emit_log(app, stage_owned.as_deref(), LogStream::Stderr, &l),
Ok(None) => {}
Err(e) => { tracing::warn!("stderr read error: {e}"); }
},
}
}
while let Ok(Some(l)) = read_decoded_line(&mut out, &mut out_buf).await {
emit_log(app, stage_owned.as_deref(), LogStream::Stdout, &l);
}
while let Ok(Some(l)) = read_decoded_line(&mut err, &mut err_buf).await {
emit_log(app, stage_owned.as_deref(), LogStream::Stderr, &l);
}
let status = child.wait().await.map_err(|e| anyhow!("waiting for child: {e}"))?;
Ok(CmdResult {
exit_code: status.code(),
})
}
struct CmdResult {
exit_code: Option<i32>,
}
/// Path to the venv hermes shim under an install root, regardless of existence.
fn venv_hermes(install_root: &Path) -> PathBuf {
if cfg!(target_os = "windows") {
install_root.join("venv").join("Scripts").join("hermes.exe")
} else {
install_root.join("venv").join("bin").join("hermes")
}
}
View on GitHub (pinned to c896c09c42)
Solutions
- Check system logs (dmesg OOM lines, Event Viewer) for evidence the child was killed.
- Free memory/close other apps and retry the update.
- Avoid force-killing the updater or its children; close windows normally so shutdown is graceful.
- If it recurs on the same step, run the printed child command manually to reproduce outside the updater.
Defensive patterns
Strategy: try-catch
Try / catch
match child.wait().await {
Ok(status) => Ok(CmdResult { exit_code: status.code() }),
Err(e) => {
// Child was killed/reaped (OOM, signal, external kill). Treat as failure with context,
// and hint at system-level causes rather than retrying blindly.
Err(anyhow!("waiting for child: {e} — the process may have been killed (OOM / signal / shutdown)"))
}
} Prevention
- Free memory and close other apps before update builds — the OOM killer is the usual cause.
- Never force-kill the updater's process tree; close windows gracefully instead.
- Run the child command manually first to confirm it completes on a constrained machine.
When it happens
Trigger: The child (hermes update / hermes desktop --build-only) gets SIGKILLed by an OOM killer, task manager, or a shutdown mid-run; the updater process itself is being torn down while awaiting; cgroup/container eviction kills the child.
Common situations: Memory-hungry electron build killed by the OOM killer; user ends the process tree from Task Manager/Activity Monitor mid-update; system sleep/shutdown during the update; WSL2 VM reclaiming memory during the build.
Related errors
- hermes update failed (exit {:?}). See {} for details.
- spawning {} {:?}: {e}
- running ditto: {e}
- install script invocation failed: {e:#}
- Another Hermes update is already running (PID {}, started {}
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/41d52a0896973cfe.
Report an issue: GitHub.