BloopAI/vibe-kanban · error
Failed to take child stderr
Error message
Failed to take child stderr
What it means
The third take: after spawn, the child's stderr handle must be piped so it can be forwarded to the SSH client. child.stderr.take() returns None when stderr was not set to Stdio::piped(), producing this error. Like the stdin/stdout variants, it signals broken internal command construction rather than a user-triggerable condition.
Source
Thrown at crates/embedded-ssh/src/handler.rs:106
cmd.current_dir(home);
}
let mut child = cmd
.spawn()
.map_err(|e| anyhow::anyhow!("Failed to spawn stdio command: {e}"))?;
let stdin = child
.stdin
.take()
.ok_or_else(|| anyhow::anyhow!("Failed to take child stdin"))?;
let stdout = child
.stdout
.take()
.ok_or_else(|| anyhow::anyhow!("Failed to take child stdout"))?;
let stderr = child
.stderr
.take()
.ok_or_else(|| anyhow::anyhow!("Failed to take child stderr"))?;
let (writer_tx, mut writer_rx) = mpsc::channel::<Vec<u8>>(64);
tokio::spawn(async move {
let mut stdin = stdin;
while let Some(data) = writer_rx.recv().await {
if stdin.write_all(&data).await.is_err() {
break;
}
if stdin.flush().await.is_err() {
break;
}
}
});
let handle = session.handle();
let stdout_task = tokio::spawn(async move {
let mut stdout = stdout;
let mut buf = vec![0u8; 8192];View on GitHub (pinned to 4deb7eca8f)
Solutions
- Ensure .stderr(Stdio::piped()) is set on the command before spawn.
- Check that no alternate construction path (e.g. PTY session) reuses this code with different Stdio config.
- Test that stderr output from a failing command is visible in the SSH client to confirm piping works.
Example fix
// before cmd.stderr(Stdio::null()); // after cmd.stderr(Stdio::piped());
Defensive patterns
Strategy: validation
Validate before calling
let mut cmd = Command::new(shell); cmd.stdin(Stdio::piped()); cmd.stdout(Stdio::piped()); cmd.stderr(Stdio::piped()); // required, otherwise take() -> None let mut child = cmd.spawn()?;
Prevention
- Always pipe stderr for stdio sessions so errors reach the SSH client.
- Add a test asserting stderr from a failing command appears on the channel.
- Avoid swapping in Stdio::null/inherit for debugging without reverting.
- Group all three Stdio settings in one helper to keep them consistent.
When it happens
Trigger: child.stderr.take() returns None because the command lacks .stderr(Stdio::piped()) at build time in spawn_stdio_session.
Common situations: Seen only if the handler's command construction was altered (e.g. stderr inherited for debugging) or partially configured; not triggerable by SSH clients.
Related errors
- Failed to take child stdin
- Failed to take child stdout
- Failed to spawn stdio command: {e}
- Channel already has an active session
- Channel not found
AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29).
Data as JSON: /api/errors/7f6e2677f791e600.
Report an issue: GitHub.