{"record":{"id":"cbb8dc006c15b1ec","repo":"NousResearch/hermes-agent","slug":"copilot-acp-process-did-not-expose-stdin-stdout-pi","errorCode":null,"errorMessage":"Copilot ACP process did not expose stdin/stdout pipes.","messagePattern":"Copilot ACP process did not expose stdin/stdout pipes\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/copilot_acp_client.py","lineNumber":529,"sourceCode":"                [self._acp_command] + self._acp_args,\n                stdin=subprocess.PIPE,\n                stdout=subprocess.PIPE,\n                stderr=subprocess.PIPE,\n                text=True, encoding='utf-8', errors='replace',\n                bufsize=1,\n                cwd=self._acp_cwd,\n                env=_build_subprocess_env(),\n                creationflags=windows_hide_flags(),\n            )\n        except FileNotFoundError as exc:\n            raise RuntimeError(\n                f\"Could not start Copilot ACP command '{self._acp_command}'. \"\n                \"Install GitHub Copilot CLI or set HERMES_COPILOT_ACP_COMMAND/COPILOT_CLI_PATH.\"\n            ) from exc\n\n        if proc.stdin is None or proc.stdout is None:\n            proc.kill()\n            raise RuntimeError(\"Copilot ACP process did not expose stdin/stdout pipes.\")\n\n        self.is_closed = False\n        with self._active_process_lock:\n            self._active_process = proc\n\n        inbox: queue.Queue[dict[str, Any]] = queue.Queue()\n        stderr_tail: deque[str] = deque(maxlen=40)\n\n        def _stdout_reader() -> None:\n            if proc.stdout is None:\n                return\n            for line in proc.stdout:\n                try:\n                    inbox.put(json.loads(line))\n                except Exception:\n                    inbox.put({\"raw\": line.rstrip(\"\\n\")})\n\n        def _stderr_reader() -> None:","sourceCodeStart":511,"sourceCodeEnd":547,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/agent/copilot_acp_client.py#L511-L547","documentation":"The Copilot ACP subprocess spawned successfully but did not provide usable stdin/stdout pipes, which the JSON-RPC protocol requires. Hermes kills the process and raises this RuntimeError. In practice this only occurs with an exotic spawn configuration (e.g. a wrapper that closes or redirects standard streams) since Popen is called with explicit PIPEs.","triggerScenarios":"HERMES_COPILOT_ACP_COMMAND points at a wrapper script/binary that closes stdin/stdout, or a platform-level spawn anomaly where the PIPE file descriptors are not available (proc.stdin/proc.stdout is None).","commonSituations":"A custom ACP shim command that daemonizes or redirects stdio; unusual shells or process supervisors interfering with inherited file descriptors. Very rare on standard setups.","solutions":["Point HERMES_COPILOT_ACP_COMMAND directly at the real copilot binary, not a wrapper that touches stdio.","Verify manually that the binary speaks line-delimited JSON-RPC on stdio: echo '<initialize request>' | copilot ... (it should respond on stdout).","Update Copilot CLI in case of a version-specific stdio bug."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Smoke-test the command speaks stdio JSON-RPC before wiring it in:\nimport subprocess\np = subprocess.run([cmd, '--help'], capture_output=True, text=True, timeout=10)\nassert p.returncode == 0, p.stderr  # a healthy binary at least runs","typeGuard":null,"tryCatchPattern":"try:\n    client = CopilotACPClient(...)\nexcept RuntimeError as e:\n    if 'did not expose stdin/stdout pipes' in str(e):\n        # replace stdio-touching wrapper with the direct binary\n        ...","preventionTips":["Point HERMES_COPILOT_ACP_COMMAND at the real binary, not a wrapper","Never wrap the ACP command in tools that redirect or close stdio","Test the binary manually with a piped JSON-RPC line first"],"tags":["copilot","acp","stdio","process"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}