Hmbown/CodeWhale · error
stderr unavailable
Error message
stderr unavailable
What it means
Thrown when `child.stderr` is None after spawning. Like the stdout case, this should be impossible while `.stderr(Stdio::piped())` is configured, so it flags a broken invariant or double-take of the pipe.
Solutions
- Verify `.stderr(Stdio::piped())` is set on the Command before spawn
- Take stderr exactly once per child
- If stderr is merged via Stdio::piped into stdout, remove the separate take
Example fix
// before .stderr(Stdio::inherit()); // then child.stderr.take() -> None // after .stderr(Stdio::piped());
Defensive patterns
Strategy: try-catch
Try / catch
let stderr = child.stderr.take()
.ok_or_else(|| anyhow::anyhow!("stderr unavailable: stderr was not piped before spawn"))?; Prevention
- Keep .stderr(Stdio::piped()) adjacent to the stderr take
- Do not merge stderr into stdout if stderr is consumed separately
- Take each pipe exactly once
When it happens
Trigger: `child.stderr.take()` returning None because stderr was not configured as piped or was already consumed.
Common situations: Someone removed the `.stderr(Stdio::piped())` configuration; stderr taken twice; merging stderr into stdout while still trying to take it separately.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Failed to capture stderr
- stdout unavailable
- 125
- Cannot resolve current binary path
- Cloud agent harness exited with code
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/7edef7522177c75c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/lib.rs:10561
let mut cmd = Command::new(exec_env.program());
cmd.args(exec_env.args())
.current_dir(&exec_env.cwd)
.stdout(Stdio::piped())
.stderr(Stdio::piped());
child_env::apply_to_command(&mut cmd, child_env::string_map_env(&exec_env.env));
let mut child = cmd
.spawn()
.map_err(|e| anyhow::anyhow!("Failed to run command: {e}"))?;
let stdout_handle = child
.stdout
.take()
.ok_or_else(|| anyhow::anyhow!("stdout unavailable"))?;
let stderr_handle = child
.stderr
.take()
.ok_or_else(|| anyhow::anyhow!("stderr unavailable"))?;
let timeout = exec_env.timeout;
let stdout_thread = std::thread::spawn(move || {
let mut reader = stdout_handle;
let mut buf = Vec::new();
let _ = reader.read_to_end(&mut buf);
buf
});
let stderr_thread = std::thread::spawn(move || {
let mut reader = stderr_handle;
let mut buf = Vec::new();
let _ = reader.read_to_end(&mut buf);
buf
});
if let Some(status) = child.wait_timeout(timeout)? {
let stdout = stdout_thread.join().unwrap_or_default();
let stderr = stderr_thread.join().unwrap_or_default();View on GitHub (pinned to 73e0f67d83)