{"record":{"id":"2a489505e8d051a2","repo":"github/copilot-sdk","slug":"cli-process-exited-before-announcing-port","errorCode":null,"errorMessage":"CLI process exited before announcing port","messagePattern":"CLI process exited before announcing port","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"python/copilot/client.py","lineNumber":4476,"sourceCode":"            \"CopilotClient._start_cli_server subprocess spawned\",\n            spawn_start,\n        )\n\n        # For stdio mode, we're ready immediately\n        if use_stdio:\n            return\n\n        # For TCP mode, wait for port announcement\n        loop = asyncio.get_event_loop()\n        process = self._process  # Capture for closure\n\n        async def read_port():\n            if not process or not process.stdout:\n                raise RuntimeError(\"Process not started or stdout not available\")\n            while True:\n                line = await loop.run_in_executor(None, process.stdout.readline)\n                if not line:\n                    raise RuntimeError(\"CLI process exited before announcing port\")\n\n                line_str = line.decode() if isinstance(line, bytes) else line\n                logger.debug(\"[CLI] %s\", line_str.rstrip())\n                match = re.search(r\"listening on port (\\d+)\", line_str, re.IGNORECASE)\n                if match:\n                    self._runtime_port = int(match.group(1))\n                    return\n\n        try:\n            port_wait_start = time.perf_counter()\n            await asyncio.wait_for(read_port(), timeout=10.0)\n            log_timing(\n                logger,\n                logging.DEBUG,\n                \"CopilotClient._start_cli_server TCP port wait complete\",\n                port_wait_start,\n                port=self._runtime_port,\n            )","sourceCodeStart":4458,"sourceCodeEnd":4494,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/python/copilot/client.py#L4458-L4494","documentation":"RuntimeError raised when the CLI process's stdout returns EOF while waiting for the 'listening on port N' announcement, meaning the process exited before it could report its TCP port. This indicates the CLI died during startup.","triggerScenarios":"In TCP mode, read_port() calls process.stdout.readline() which returns b'' (EOF) because the CLI process exited before printing 'listening on port <n>'.","commonSituations":"Invalid CLI flags or corrupt installation cause the CLI to crash immediately; the binary is a wrong/incompatible version; missing runtime dependencies make the CLI exit at launch; port/permission issues kill the server before announcement.","solutions":["Check the CLI binary runs standalone (e.g. copilot --version) and reinstall/upgrade if it crashes","Inspect stderr/logs for the CLI's actual crash reason (invalid flag, missing dep)","Verify the installed CLI version matches what this SDK expects","Increase debugging: enable SDK debug logging to capture CLI output lines before exit"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import shutil\nif shutil.which(\"copilot\") is None:\n    raise SystemExit(\"CLI binary not found or not runnable\")","typeGuard":null,"tryCatchPattern":"try:\n    await client.start()\nexcept RuntimeError as e:\n    if \"exited before announcing port\" in str(e):\n        log_cli_stderr_and_reinstall_or_report(e)\n    else:\n        raise","preventionTips":["Verify the CLI binary runs standalone before launching through the SDK","Pin a CLI version compatible with the SDK","Capture CLI stderr in logs for post-mortem","Run a health check (e.g. copilot --version) at deployment startup"],"tags":["subprocess","crash","startup","tcp"],"backgroundTag":"process-exited-unexpectedly","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}