{"record":{"id":"1cb48d4f81df1671","repo":"Hmbown/CodeWhale","slug":"failed-to-capture-stdout","errorCode":null,"errorMessage":"Failed to capture stdout","messagePattern":"Failed to capture stdout","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/shell.rs","lineNumber":2538,"sourceCode":"            {\n                windows_job = attach_windows_job(&child, original_command);\n            }\n\n            let stdin_handle = child.stdin.take().map(StdinWriter::Pipe);\n\n            let (stdout_thread, stderr_thread) =\n                if let (Some(reader), Some(output)) = (combined_reader, bounded_output.as_ref()) {\n                    (\n                        Some(spawn_bounded_reader_thread(reader, Arc::clone(output))),\n                        None,\n                    )\n                } else {\n                    let stdout_handle = child.stdout.take().ok_or_else(|| {\n                        #[cfg(windows)]\n                        terminate_unregistered_process(&mut child, windows_job.as_ref());\n                        #[cfg(not(windows))]\n                        terminate_unregistered_process(&mut child);\n                        anyhow!(\"Failed to capture stdout\")\n                    })?;\n                    let stderr_handle = child.stderr.take().ok_or_else(|| {\n                        #[cfg(windows)]\n                        terminate_unregistered_process(&mut child, windows_job.as_ref());\n                        #[cfg(not(windows))]\n                        terminate_unregistered_process(&mut child);\n                        anyhow!(\"Failed to capture stderr\")\n                    })?;\n                    (\n                        Some(spawn_reader_thread(\n                            stdout_handle,\n                            Arc::clone(&stdout_buffer),\n                        )),\n                        stderr_buffer\n                            .as_ref()\n                            .map(|buffer| spawn_reader_thread(stderr_handle, Arc::clone(buffer))),\n                    )\n                };","sourceCodeStart":2520,"sourceCodeEnd":2556,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/tools/shell.rs#L2520-L2556","documentation":"When a spawned child is handled with separated stdout/stderr reader threads (the non-combined, non-bounded path), child.stdout must be Some — i.e. the child was spawned with piped stdout. If stdout was not piped (take() yields None), the already-spawned child is terminated (terminate_unregistered_process, plus Windows job cleanup) and this error returns. It is an internal invariant: output capture was assumed but the spawn did not provide the pipe.","triggerScenarios":"A spawn path or platform behavior where the child is created without Stdio::piped() stdout but the separated-reader branch is taken; e.g. an internal regression or a mode mismatch between requested capture and spawn configuration.","commonSituations":"Rare; users normally cannot trigger it via the tool API — output capture is requested implicitly. Would surface after code changes to spawn options.","solutions":["Retry the command once — transient spawn misconfiguration is unlikely but cheap to rule out.","If reproducible, report upstream with the exact command, background/tty flags, and platform.","As a workaround, run the command in background mode with bounded output, which uses the combined reader path."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"let out = match exec_shell(cmd, dir, opts).await {\n    Ok(o) => o,\n    Err(e) if e.to_string().contains(\"Failed to capture stdout\") => {\n        // reader-thread invariant broke; retry once, then fall back to bounded/background mode\n        exec_shell(cmd, dir, opts).await\n            .or_else(|_| exec_shell_background_bounded(cmd, dir))?\n    }\n    Err(e) => return Err(e),\n};","preventionTips":["Prefer background execution with bounded output for commands whose capture path you control.","If it reproduces with one specific command/flag combination, report it — this path assumes piped stdout at spawn."],"tags":["shell","process-io","stdout","spawn","invariant"],"backgroundTag":"process-io-capture-failed","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}