BloopAI/vibe-kanban · error
Failed to take child stdout
Error message
Failed to take child stdout
What it means
Same as the stdin variant: after spawning the child, spawn_stdio_session takes the child's stdout handle and fails if it is None. Stdout is None only when the command was not configured with Stdio::piped() for stdout, but the stdio session needs to relay the child's output back over the SSH channel.
Source
Thrown at crates/embedded-ssh/src/handler.rs:102
for (k, v) in env {
cmd.env(k, v);
}
if let Ok(home) = std::env::var("HOME") {
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;
}
}
});
View on GitHub (pinned to 4deb7eca8f)
Solutions
- Add/restore .stdout(Stdio::piped()) on the command before spawn.
- Verify no code path replaces stdout with Stdio::inherit or Stdio::null for stdio sessions.
- Add a unit/integration test that spawns a trivial command through spawn_stdio_session and asserts output is relayed, catching regressions.
Example fix
// before cmd.stdout(Stdio::inherit()); // after cmd.stdout(Stdio::piped());
Defensive patterns
Strategy: validation
Validate before calling
let mut cmd = Command::new(shell); cmd.stdin(Stdio::piped()); cmd.stdout(Stdio::piped()); // required, otherwise take() -> None let mut child = cmd.spawn()?;
Prevention
- Keep .stdout(Stdio::piped()) on every command spawned for stdio relay.
- Cover stdout relay with an integration test (echo output through the SSH channel).
- Review any refactor of command construction for dropped Stdio settings.
- Treat this error as an internal invariant break; alert rather than retry.
When it happens
Trigger: child.stdout.take() returns None because the spawned command lacks .stdout(Stdio::piped()) — an internal construction bug, not user input.
Common situations: Encountered only after code changes to command construction in the embedded-ssh handler; users cannot cause it remotely.
Related errors
- Failed to take child stdin
- Failed to take child stderr
- 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/0d028e6dcab2f547.
Report an issue: GitHub.