{"record":{"id":"fb05edcbe8c15a77","repo":"zeroclaw-labs/zeroclaw","slug":"failed-to-write-args-to-plugin-stdin","errorCode":null,"errorMessage":"failed to write args to plugin '{}' stdin: {}","messagePattern":"failed to write args to plugin '(.+?)' stdin: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-hardware/src/subprocess.rs","lineNumber":154,"sourceCode":"                stdin.write_all(b\"\\n\").await?;\n                Ok::<(), std::io::Error>(())\n            }\n            .await;\n            if let Err(e) = write_result\n                && e.kind() != std::io::ErrorKind::BrokenPipe\n            {\n                let _ = child.kill().await;\n                ::zeroclaw_log::record!(\n                    ERROR,\n                    ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)\n                        .with_outcome(::zeroclaw_log::EventOutcome::Failure)\n                        .with_attrs(::serde_json::json!({\n                            \"plugin\": self.manifest.tool.name,\n                            \"error\": format!(\"{}\", e),\n                        })),\n                    \"subprocess plugin: failed to write args to stdin\"\n                );\n                anyhow::bail!(\n                    \"failed to write args to plugin '{}' stdin: {}\",\n                    self.manifest.tool.name,\n                    e\n                );\n            }\n            // stdin dropped here → child receives EOF\n        }\n\n        // Take stdout and stderr handles before we move `child`.\n        let stdout_handle = child.stdout.take();\n        let stderr_handle = child.stderr.take();\n\n        // Read one line from stdout with a hard timeout.\n        let read_result = match stdout_handle {\n            None => {\n                // No stdout — kill and error.\n                let _ = child.kill().await;\n                return Ok(ToolResult {","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-hardware/src/subprocess.rs#L136-L172","documentation":"SubprocessTool::execute spawns the plugin with piped stdio and writes the JSON args plus a newline to its stdin. BrokenPipe is deliberately tolerated (children that never read stdin are legal), so this bail fires only for other I/O errors during the write — and the child is killed first. The zeroclaw log record includes the plugin name and the io::Error for diagnosis.","triggerScenarios":"The child's stdin fails at the OS level with something other than EPIPE: the pipe torn down by a concurrent kill/timeout, a plugin binary that crashes instantly while stdin is being written, or a resource-exhausted host (fd limits) failing the pipe write.","commonSituations":"Plugin binaries crashing at startup; hosts at fd/memory limits running many subprocess plugins; races between the subprocess timeout machinery and the stdin write.","solutions":["Reproduce the plugin manually: `echo '{\"args\":1}' | ./plugin-binary` and check it starts without crashing","Check zeroclaw logs — the 'failed to write args to stdin' event carries the plugin name and io::Error kind","Verify the manifest's tool name and binary_path point at the intended executable and it is runnable on this platform","On resource-starved hosts, raise fd limits or reduce concurrent subprocess plugins"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"let ok = std::process::Command::new(&plugin_binary)\n    .arg(\"--help\")\n    .output()\n    .map(|o| o.status.success())\n    .unwrap_or(false);\nif !ok {\n    anyhow::bail!(\"plugin does not run standalone; check binary and manifest\");\n}","typeGuard":null,"tryCatchPattern":"match tool.execute(args).await {\n    Err(e) if format!(\"{e}\").contains(\"failed to write args to\") => {\n        // plugin's stdin failed at OS level (EPIPE is tolerated elsewhere):\n        // verify the plugin starts standalone, check the zeroclaw log event,\n        // then retry once\n    }\n    rest => rest,\n}","preventionTips":["Test plugin binaries standalone (`echo args | ./plugin`) before registering them","Keep plugin manifests' binary_path correct and executable for the host platform","Watch fd/memory limits when running many subprocess plugins concurrently"],"tags":["subprocess","plugin","stdin","pipe","io-error"],"backgroundTag":"plugin-stdin-write-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}