{"record":{"id":"31021be4124e4f09","repo":"tinyhumansai/openhuman","slug":"claude-child-stdout-missing","errorCode":null,"errorMessage":"claude child stdout missing","messagePattern":"claude child stdout missing","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/openhuman/inference/provider/claude_code/driver.rs","lineNumber":406,"sourceCode":"\n    let mut child = cmd\n        .spawn()\n        .map_err(|e| anyhow::anyhow!(\"failed to spawn `claude`: {e}\"))?;\n    if let Some(mut stdin) = child.stdin.take() {\n        stdin\n            .write_all(&stdin_bytes)\n            .await\n            .map_err(|e| anyhow::anyhow!(\"write stdin: {e}\"))?;\n        stdin\n            .shutdown()\n            .await\n            .map_err(|e| anyhow::anyhow!(\"close stdin: {e}\"))?;\n    }\n\n    let mut stdout = child\n        .stdout\n        .take()\n        .ok_or_else(|| anyhow::anyhow!(\"claude child stdout missing\"))?;\n    let mut stderr = child\n        .stderr\n        .take()\n        .ok_or_else(|| anyhow::anyhow!(\"claude child stderr missing\"))?;\n\n    let mut parser = StreamJsonParser::new();\n    let mut mapper = EventMapper::new();\n    let mut buf = [0u8; 8192];\n\n    // Drain stderr in parallel into a buffer for diagnostics.\n    let stderr_task = tokio::spawn(async move {\n        let mut acc = String::new();\n        let mut tmp = [0u8; 4096];\n        while let Ok(n) = stderr.read(&mut tmp).await {\n            if n == 0 {\n                break;\n            }\n            acc.push_str(&String::from_utf8_lossy(&tmp[..n]));","sourceCodeStart":388,"sourceCodeEnd":424,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/inference/provider/claude_code/driver.rs#L388-L424","documentation":"Taking the piped stdout handle from the spawned claude child returned None. Unreachable in normal operation because Stdio::piped was requested at spawn; hitting it means the stdio configuration was lost or the handle already taken — a type-guard failure on the Option, not an IO error.","triggerScenarios":"Thrown at src/openhuman/inference/provider/claude_code/driver.rs:406 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Ensure stdout is configured as Stdio::piped when spawning","Audit for any code taking the handle before the driver"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}