Hmbown/CodeWhale · error
Failed to wait for `gh api
Error message
Failed to wait for `gh api`: {e} What it means
Raised when the code fails to reap the spawned `gh api` child process via `wait_with_output()` while posting a PR review. This is an OS-level I/O failure around the child process (spawn/pipe/read), not a GitHub HTTP error — HTTP-level failures are surfaced separately via the stderr bail right after. The review post is aborted with an uncertain publication state.
Solutions
- Retry the review-post operation; this is usually a transient OS-level failure
- Check system resource limits (ulimit -n for fd exhaustion) and raise if processes/fds are leaking
- Ensure no other code path in the app reaps the same child (would cause wait to fail)
- If persistent, capture `gh api` output via a temp file instead of pipes to sidestep pipe-read failures
Example fix
// before
let output = child.wait_with_output()
.map_err(|e| anyhow::anyhow!("Failed to wait for `gh api`: {e}"))?;
// after
let output = match child.wait_with_output() {
Ok(o) => o,
Err(e) => { tracing::warn!("gh api wait failed: {e}; retrying once"); child2.wait_with_output()? }
}; Defensive patterns
Strategy: try-catch
Try / catch
// Rust
let output = child.wait_with_output()
.map_err(|e| anyhow::anyhow!("Failed to wait for `gh api`: {e}"))
.with_context(|| format!("waiting for gh api on {repo}#{number}"))?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
bail!("gh api failed: {stderr}");
} Prevention
- Do not double-reap child processes elsewhere in the app
- Keep fd/process limits healthy in CI containers
- Retry once on transient wait failures before surfacing to the user
- Log the repo/PR context so failed reviews can be re-posted safely
When it happens
Trigger: `child.wait_with_output()` returns Err while waiting for the `gh api POST repos/{repo}/pulls/{number}/reviews` process — e.g. the process was reaped elsewhere first, the runtime could not read its stdout/stderr pipes, or the process was killed in a way that makes wait fail.
Common situations: Process reapers/monitors that double-reap children; resource exhaustion (fork failures, fd limits) under load; container runtimes with unusual process semantics; intermittent OS-level I/O errors.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Failed to write review payload
- Cannot resolve current binary path
- Cloud agent harness exited with code
- exited
- Command failed with exit code
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/8fb34e15ce1e4f59.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/lib.rs:9738
.arg(format!("repos/{repo}/pulls/{number}/reviews"))
.arg("--input")
.arg("-")
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped());
let mut child = cmd
.spawn()
.map_err(|e| anyhow::anyhow!("Failed to run `gh api`: {e}"))?;
*publication = ReviewPublication::Uncertain;
if let Some(stdin) = child.stdin.as_mut() {
use std::io::Write;
stdin
.write_all(serde_json::to_string(&payload)?.as_bytes())
.map_err(|e| anyhow::anyhow!("Failed to write review payload: {e}"))?;
}
let output = child
.wait_with_output()
.map_err(|e| anyhow::anyhow!("Failed to wait for `gh api`: {e}"))?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
bail!("gh api POST repos/{repo}/pulls/{number}/reviews failed: {stderr}");
}
*publication = ReviewPublication::Posted;
Ok(())
}
/// Publish a completed PR review exactly once: resolve the repository, render
/// the summary, and include every comment whose position the diff confirms.
/// A failed request can have an uncertain remote outcome, so reconciliation
/// and any retry stay under the caller's control rather than risking a duplicate.
fn post_pr_review(
number: u32,
view: &GhPullRequest,
repo: Option<&str>,
review: &crate::tools::review::ReviewOutput,
diff: &str,View on GitHub (pinned to 73e0f67d83)