{"record":{"id":"eacf1222c27f8a18","repo":"affaan-m/ECC","slug":"child-stderr-was-not-piped","errorCode":null,"errorMessage":"Child stderr was not piped","messagePattern":"Child stderr was not piped","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"ecc2/src/session/runtime.rs","lineNumber":166,"sourceCode":"            .stdout(Stdio::piped())\n            .stderr(Stdio::piped())\n            .spawn()\n            .with_context(|| format!(\"Failed to start process for session {}\", session_id))?;\n\n        let stdout = match child.stdout.take() {\n            Some(stdout) => stdout,\n            None => {\n                let _ = child.kill().await;\n                let _ = child.wait().await;\n                anyhow::bail!(\"Child stdout was not piped\");\n            }\n        };\n        let stderr = match child.stderr.take() {\n            Some(stderr) => stderr,\n            None => {\n                let _ = child.kill().await;\n                let _ = child.wait().await;\n                anyhow::bail!(\"Child stderr was not piped\");\n            }\n        };\n\n        let pid = child\n            .id()\n            .ok_or_else(|| anyhow::anyhow!(\"Spawned process did not expose a process id\"))?;\n        db_writer.update_pid(Some(pid)).await?;\n        db_writer.update_state(SessionState::Running).await?;\n        db_writer.touch_heartbeat().await?;\n\n        let heartbeat_writer = db_writer.clone();\n        let heartbeat_task = tokio::spawn(async move {\n            let mut ticker = time::interval(heartbeat_interval);\n            ticker.set_missed_tick_behavior(MissedTickBehavior::Delay);\n            loop {\n                ticker.tick().await;\n                if heartbeat_writer.touch_heartbeat().await.is_err() {\n                    break;","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/affaan-m/ECC/blob/06c5e118c4d3e6c3b7f9445f973a2194c82de193/ecc2/src/session/runtime.rs#L148-L184","documentation":"Same invariant as stdout: capture_command_output requires piped stderr, and child.stderr.take() returned None. The child is killed and waited before the error is raised, indicating the Command was built without Stdio::piped for stderr.","triggerScenarios":"Thrown at ecc2/src/session/runtime.rs:166 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Spawn the child process with stderr set to piped before reading it.","Ensure no earlier code consumed or detached the stderr handle."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"06c5e118c4d3e6c3b7f9445f973a2194c82de193","analyzedAt":"2026-08-18T11:27:13.915Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}