{"record":{"id":"a9aade893eb96823","repo":"tinyhumansai/openhuman","slug":"pool-worker-closed-stdout","errorCode":null,"errorMessage":"pool worker closed stdout","messagePattern":"pool worker closed stdout","errorType":"exception","errorClass":"SubmitError","httpStatus":null,"severity":"error","filePath":"src/openhuman/runtime/pool/worker.rs","lineNumber":256,"sourceCode":"        // Fixed deadline: `continue`ing over unparseable / mismatched-id lines\n        // must NOT reset the wedged-worker timeout, so it bounds the total wait.\n        let deadline = hard_timeout.map(|t| tokio::time::Instant::now() + t);\n        loop {\n            let next = match deadline {\n                Some(dl) => match tokio::time::timeout_at(dl, self.responses.next_line()).await {\n                    Ok(inner) => inner,\n                    Err(_) => {\n                        return Err(SubmitError::post(anyhow::anyhow!(\n                            \"pool worker job timed out (hard deadline; worker wedged)\"\n                        )))\n                    }\n                },\n                None => self.responses.next_line().await,\n            };\n            let line = match next {\n                Ok(Some(line)) => line,\n                Ok(None) => {\n                    return Err(SubmitError::post(anyhow::anyhow!(\n                        \"pool worker closed stdout\"\n                    )))\n                }\n                Err(error) => {\n                    return Err(SubmitError::post(\n                        anyhow::Error::new(error).context(\"reading pool job response\"),\n                    ))\n                }\n            };\n            let response: PoolJobResponse = match serde_json::from_str(&line) {\n                Ok(response) => response,\n                Err(error) => {\n                    tracing::warn!(\n                        lang = self.launch.lang.id(),\n                        \"[runtime_pool] unparseable worker line skipped: {error}\"\n                    );\n                    continue;\n                }","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/runtime/pool/worker.rs#L238-L274","documentation":"Returned from the response-reading loop when the worker's stdout stream ends (responses.next_line() yields None) while waiting for a job completion line. It means the pool worker process exited or closed its stdout mid-job — e.g. a reused idle worker died between jobs, or the child crashed. Distinguished from the timeout path so that the fixed deadline is only spent on real waiting; lines that fail to parse or carry a mismatched id are skipped without resetting the deadline.","triggerScenarios":"Thrown at src/openhuman/runtime/pool/worker.rs:256 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Treat as terminal: the job may or may not have run before the worker died, so do not auto-retry the same job id.","Replace/restart the dead pool worker before submitting further jobs.","Log the worker pid and job id to correlate with any partial side effects the job may have produced.","Check stderr/exit status of the worker process for the underlying crash cause (OOM, panic in the spawned tool)."],"exampleFix":null,"handlingStrategy":"try-catch","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-14T00:17:10.932Z"}