{"record":{"id":"e72ab8a185c8fe18","repo":"github/copilot-sdk","slug":"client-is-not-connected-call-start-first-e72ab8","errorCode":null,"errorMessage":"Client is not connected. Call start() first.","messagePattern":"Client is not connected\\. Call start\\(\\) first\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/copilot/client.py","lineNumber":1826,"sourceCode":"            if runtime_path is None:\n                raise RuntimeError(\n                    f\"In-process runtime library not found next to '{explicit_cli}'.\"\n                )\n            self._cli_path_source = \"environment\"\n            self._inprocess_cli_entrypoint = explicit_cli\n            return runtime_path\n\n        from ._cli_download import ensure_runtime_wrapper\n\n        wrapper_path = Path(ensure_runtime_wrapper())\n        self._cli_path_source = \"downloaded\"\n        return str(wrapper_path.with_name(\"runtime.node\"))\n\n    @property\n    def rpc(self) -> ServerRpc:\n        \"\"\"Typed server-scoped RPC methods.\"\"\"\n        if self._rpc is None:\n            raise RuntimeError(\"Client is not connected. Call start() first.\")\n        return self._rpc\n\n    @property\n    def runtime_port(self) -> int | None:\n        \"\"\"TCP port the runtime is listening on, when using TCP transport.\n\n        Useful for multi-client scenarios where a second client needs to connect\n        to the same runtime. Only available after :meth:`start` completes and\n        only when not using stdio transport.\n        \"\"\"\n        return self._runtime_port\n\n    def _parse_cli_url(self, url: str) -> tuple[str, int]:\n        \"\"\"\n        Parse CLI URL into host and port.\n\n        Supports formats: \"host:port\", \"[ipv6]:port\", \"http://host:port\",\n        \"https://host:port\", or just \"port\".","sourceCodeStart":1808,"sourceCodeEnd":1844,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/python/copilot/client.py#L1808-L1844","documentation":"This RuntimeError is thrown by the `rpc` property of CopilotClient when the internal `_rpc` handle has not been initialized. The client only creates `_rpc` during `start()` (or `connect()`), so accessing server-scoped RPC methods before the transport is up is an invalid state. The library throws early instead of returning None to prevent confusing downstream attribute errors.","triggerScenarios":"Accessing `client.rpc` (or any property built on it) before calling `await client.start()`, after `stop()`/`force_stop()` has torn the connection down, or after a failed `start()` left the client in the 'error' state.","commonSituations":"Forgetting to await start() in async code; calling RPC methods in a script that stopped the client earlier; reusing a client object after context-manager exit (`async with` block ended); a start() failure caught and ignored, then RPC attempted anyway.","solutions":["Call `await client.start()` before accessing `client.rpc`.","Check `client._state` / wrap usage in `async with CopilotClient(...) as client:` so lifecycle is managed automatically.","If the client was stopped, create a new CopilotClient instance instead of reusing it.","Inspect logs from the failed start() if start() was called but the state is 'error'."],"exampleFix":"// before\nclient = CopilotClient(...)\nresult = await client.rpc.listModels()\n// after\nclient = CopilotClient(...)\nawait client.start()\nresult = await client.rpc.listModels()","handlingStrategy":"try-catch","validationCode":"if not hasattr(client, \"rpc\") or client._rpc is None:\n    await client.start()","typeGuard":"def is_connected(client) -> bool:\n    return getattr(client, \"_rpc\", None) is not None","tryCatchPattern":"try:\n    rpc = client.rpc\nexcept RuntimeError as e:\n    if \"not connected\" in str(e):\n        await client.start()\n        rpc = client.rpc\n    else:\n        raise","preventionTips":["Always manage the client with `async with CopilotClient(...) as client:`","Call start() immediately after construction and before any RPC access","Never reuse a client after stop()/context exit — create a new one","Check connection state before RPC calls in long-lived services"],"tags":["python","lifecycle","rpc","not-connected"],"backgroundTag":"invalid-state-transition","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"}