{"record":{"id":"d2ffc8f6d8f9df67","repo":"Hmbown/CodeWhale","slug":"failed-to-wait-on-program-e","errorCode":null,"errorMessage":"Failed to wait on {program}: {e}","messagePattern":"Failed to wait on (.+?): (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tui/clipboard.rs","lineNumber":593,"sourceCode":"}\n\n#[cfg(all(target_os = \"linux\", not(target_env = \"ohos\"), not(test)))]\nfn write_text_with_wlcopy_using_argv(program: &str, text: &str) -> Result<()> {\n    let mut child = Command::new(program)\n        .stdin(Stdio::piped())\n        .stdout(Stdio::null())\n        .stderr(Stdio::null())\n        .spawn()\n        .map_err(|e| anyhow::anyhow!(\"Failed to run {program}: {e}\"))?;\n    if let Some(mut stdin) = child.stdin.take() {\n        stdin\n            .write_all(text.as_bytes())\n            .map_err(|e| anyhow::anyhow!(\"Failed to write to {program}: {e}\"))?;\n    }\n    // stdin is dropped here, closing the pipe so wl-copy flushes.\n    let status = child\n        .wait()\n        .map_err(|e| anyhow::anyhow!(\"Failed to wait on {program}: {e}\"))?;\n    if !status.success() {\n        bail!(\"{program} exited with {status}\");\n    }\n    Ok(())\n}\n\n#[cfg(not(test))]\nfn write_text_to_terminal_client(text: &str, in_tmux: bool) -> Result<()> {\n    if in_tmux {\n        return write_text_with_tmux(text);\n    }\n    write_text_with_osc52(text)\n}\n\n#[cfg(not(test))]\nfn write_text_with_tmux(text: &str) -> Result<()> {\n    write_text_with_tmux_using_argv(\"tmux\", &[], text)\n}","sourceCodeStart":575,"sourceCodeEnd":611,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/tui/clipboard.rs#L575-L611","documentation":"child.wait() on the wl-copy process failed in write_text_with_wlcopy_using_argv. The copy path waits synchronously after stdin drops (the drop closes the pipe so wl-copy flushes). wait() errors are rare infrastructure failures - ECHILD if the child was already reaped elsewhere, or an OS-level interrupt - distinct from wl-copy exiting non-zero, which is a separate bail.","triggerScenarios":"std::process::Child::wait returns Err: a subreaper/process supervisor reaped the wl-copy child before the TUI could, pidfd or SIGCHLD handling interfered, or a rare kernel errno during waitpid.","commonSituations":"Running under containers, systemd user sessions, s6, or any subreaper that reaps grandchildren; global signal-handling libraries.","solutions":["Reproduce manually: `printf x | wl-copy; echo $?` - if this works, the environment is reaping children","Disable or scope the subreaper/supervisor for the TUI process","Prefer the OSC 52/tmux path in that environment if the issue persists"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"let status = match child.wait() {\n    Ok(status) => status,\n    Err(e) if e.raw_os_error() == Some(10) /* ECHILD: reaped elsewhere */ => {\n        assume_child_exited(); // supervisor reaped it; not a clipboard failure\n        return Ok(());\n    }\n    Err(e) => return Err(anyhow::anyhow!(\"Failed to wait on wl-copy: {e}\")),\n};","preventionTips":["Avoid running the TUI as a child of subreapers that reap grandchildren","Distinguish wait() infrastructure errors from helper non-zero exits in error handling","Log the raw OS errno to identify supervisor interference quickly"],"tags":["clipboard","wl-clipboard","waitpid","subreaper"],"backgroundTag":"child-process-wait-failed","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}