Hmbown/CodeWhale · error
PR stderr reader failed
Error message
PR stderr reader failed
What it means
Identical to the stdout case but for stderr: `run_command` reads the child's stderr on its own thread and `join()`s it. A panicked or poisoned stderr reader thread becomes "PR stderr reader failed", aborting the bounded-capture contract rather than returning truncated diagnostics.
Solutions
- Retry the operation; transient reader panics usually do not repeat
- Check what the underlying command writes to stderr and whether output volume can be reduced
- Verify system memory available to the TUI process
- If deterministic, treat as a bug in `run_command`'s reader threads and fix/report it
Defensive patterns
Strategy: retry
Try / catch
match run_command(ws, Program::Git, &args) { Err(e) if e.to_string().contains("stderr reader failed") => run_with_retry(ws, Program::Git, &args, 2), Err(e) => Err(e), Ok(v) => Ok(v) } Prevention
- Retry bounded subprocess capture on transient reader failures
- Reduce noisy stderr from underlying git/gh commands
- Investigate repeated occurrences as a run_command reader-thread bug
When it happens
Trigger: The stderr reader thread panics during `fetch_view`, `fetch_diff`, `context_blob`, or `git` subprocess execution; typically after a huge or adversarial stderr stream or a poisoned shared buffer.
Common situations: Verbose git/gh error output on a failing command; memory pressure; a prior panic poisoning state shared with the reader threads.
Related errors
- PR stdout reader failed
- inline stderr logger panicked
- lane proxy stderr logger panicked
- AT-SPI action failed
- Cannot open session : its queued input is already open in…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/9202435cd5fa5da5.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/review_pr.rs:502
.stderr
.take()
.context("PR command stderr unavailable")?;
let stdout = std::thread::spawn(move || read_bounded(stdout, MAX_OUTPUT_BYTES));
let stderr = std::thread::spawn(move || read_bounded(stderr, 64 * 1024));
let status = match child.wait_timeout(Duration::from_secs(60))? {
Some(status) => status,
None => {
let _ = child.kill();
let _ = child.wait();
bail!("PR input command timed out; no partial output was accepted");
}
};
let stdout = stdout
.join()
.map_err(|_| anyhow::anyhow!("PR stdout reader failed"))??;
let stderr = stderr
.join()
.map_err(|_| anyhow::anyhow!("PR stderr reader failed"))??;
if stdout.len() > MAX_OUTPUT_BYTES || stderr.len() > 64 * 1024 {
bail!(
"PR input exceeds the bounded capture limit (8 MiB diff); no partial output was accepted"
);
}
if !status.success() {
bail!(
"PR input command failed: {}",
String::from_utf8_lossy(&stderr).trim()
);
}
String::from_utf8(stdout).context("PR diff is not valid UTF-8; no lossy review is accepted")
}
#[cfg(test)]
mod tests {
use super::*;
View on GitHub (pinned to 73e0f67d83)