{"record":{"id":"0684e752ba706438","repo":"github/copilot-sdk","slug":"failed-to-connect-to-cli-server-at-host-port","errorCode":null,"errorMessage":"Failed to connect to CLI server at {host}:{port}: {e}","messagePattern":"Failed to connect to CLI server at (.+?):(.+?): (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/copilot/client.py","lineNumber":4674,"sourceCode":"            tcp_connect_start = time.perf_counter()\n            logger.info(\n                \"CopilotClient._connect_via_tcp connecting to CLI server\",\n                extra={\"host\": self._actual_host, \"port\": self._runtime_port},\n            )\n            sock = socket.create_connection(\n                (self._actual_host, self._runtime_port), timeout=TCP_CONNECTION_TIMEOUT\n            )\n            sock.settimeout(None)  # Remove timeout after connection\n            log_timing(\n                logger,\n                logging.DEBUG,\n                \"CopilotClient._connect_via_tcp TCP connect complete\",\n                tcp_connect_start,\n                host=self._actual_host,\n                port=self._runtime_port,\n            )\n        except OSError as e:\n            raise RuntimeError(\n                f\"Failed to connect to CLI server at {self._actual_host}:{self._runtime_port}: {e}\"\n            )\n\n        # Create a file-like wrapper for the socket\n        sock_file = sock.makefile(\"rwb\", buffering=0)\n\n        # Create a mock process object that JsonRpcClient expects\n        class SocketWrapper:\n            def __init__(self, sock_file, sock_obj):\n                self.stdin = sock_file\n                self.stdout = sock_file\n                self.stderr = None\n                self._socket = sock_obj\n\n            def terminate(self):\n                import socket as _socket_mod\n\n                # shutdown() sends TCP FIN to the server (triggering","sourceCodeStart":4656,"sourceCodeEnd":4692,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/python/copilot/client.py#L4656-L4692","documentation":"Wraps socket errors raised by socket.create_connection in CopilotClient._connect_via_tcp. It means the TCP handshake to the CLI server at the given host:port failed - connection refused, wrong port, unreachable host, or the TCP_CONNECTION_TIMEOUT elapsed before the CLI started listening - with the original exception chained as the cause.","triggerScenarios":"socket.create_connection raises OSError during _connect_via_tcp: server not listening on the announced port, wrong host, firewall blocking, IPv6/IPv4 resolution issues, or the CLI died right after announcing its port.","commonSituations":"Port announced but server crashed immediately (race); connecting to 'localhost' when the server bound only to 127.0.0.1 or ::1; firewall/VPN blocking the port; containers where host differs; port already reused by another process.","solutions":["Retry the connect with a short delay (server may need a moment after announcement)","Verify the host configuration matches the interface the CLI bound to (127.0.0.1 vs localhost vs 0.0.0.0)","Check firewall/VPN rules for the chosen port range","Confirm the CLI process is still alive when this error occurs","Configure a fixed known port to avoid announcement/connect races"],"exampleFix":"// before\nawait client._connect_via_tcp()  # transient refusal right after startup\n\n// after\nfor attempt in range(5):\n    try:\n        await client._connect_via_tcp()\n        break\n    except RuntimeError as e:\n        if attempt == 4: raise\n        await asyncio.sleep(0.5)","handlingStrategy":"retry","validationCode":"import socket\nsock = socket.socket()\nif not connectable(client._actual_host, client._runtime_port):\n    schedule_retry()","typeGuard":null,"tryCatchPattern":"try:\n    await client._connect_via_tcp()\nexcept RuntimeError as e:\n    if \"Failed to connect to CLI server\" in str(e):\n        await asyncio.sleep(0.5)\n        await client._connect_via_tcp()  # bounded retry loop recommended\n    else:\n        raise","preventionTips":["Add a small bounded retry with backoff after CLI startup","Match host config to the interface the CLI binds (127.0.0.1 vs ::1)","Whitelist the port range in firewall/VPN policies","Use a fixed configured port to avoid announcement/connect races"],"tags":["network","tcp","connection","socket"],"backgroundTag":"connection-refused","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"}