{"record":{"id":"dc92cb66b2b201fa","repo":"github/copilot-sdk","slug":"errors-during-copilotclient-stop","errorCode":null,"errorMessage":"errors during CopilotClient.stop()","messagePattern":"errors during CopilotClient\\.stop\\(\\)","errorType":"exception","errorClass":"ExceptionGroup","httpStatus":null,"severity":"warning","filePath":"python/copilot/client.py","lineNumber":2175,"sourceCode":"                        )\n                    except subprocess.TimeoutExpired as e:\n                        errors.append(\n                            StopError(\n                                message=(\n                                    f\"Timed out waiting for CLI process to exit after kill: {e}\"\n                                )\n                            )\n                        )\n            if self._process is self._cli_process:\n                self._process = None\n            self._cli_process = None\n\n        self._state = \"disconnected\"\n        if not self._is_external_server:\n            self._runtime_port = None\n\n        if errors:\n            raise ExceptionGroup(\"errors during CopilotClient.stop()\", errors)\n\n    async def force_stop(self) -> None:\n        \"\"\"\n        Forcefully stop the CLI server without graceful cleanup.\n\n        Use this when :meth:`stop` fails or takes too long. This method:\n        - Clears all sessions immediately without destroying them\n        - Force closes the connection (closes the underlying transport)\n        - Kills the CLI process (if spawned by this client)\n\n        Example:\n            >>> # If normal stop hangs, force stop\n            >>> try:\n            ...     await asyncio.wait_for(client.stop(), timeout=5.0)\n            ... except asyncio.TimeoutError:\n            ...     await client.force_stop()\n        \"\"\"\n        # Clear sessions immediately without trying to destroy them","sourceCodeStart":2157,"sourceCodeEnd":2193,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/python/copilot/client.py#L2157-L2193","documentation":"CopilotClient.stop() performs graceful cleanup (closing sessions, shutting down RPC and the CLI process) and collects any exceptions raised by individual cleanup steps. If one or more steps failed, it raises an ExceptionGroup titled 'errors during CopilotClient.stop()' containing all of them. This follows Python 3.11+ exception-group semantics so partial failures are not silently swallowed.","triggerScenarios":"Calling `await client.stop()` when one or more cleanup sub-operations raise — e.g. closing a session fails, the RPC connection is already broken, or terminating the CLI process errors.","commonSituations":"Network/process already dead so graceful shutdown can't complete; sessions leaked or in a bad state; calling stop() twice with an interrupted first stop; timeouts during graceful shutdown.","solutions":["Unpack the group: `except*` (3.11+) or iterate `e.exceptions` to see each failure.","Call `await client.force_stop()` if graceful stop fails or hangs — it skips graceful cleanup.","Inspect per-session health before stopping; close/abort problem sessions individually first.","Upgrade the CLI/library if the failures point to known shutdown bugs."],"exampleFix":"// before\nawait client.stop()\n// after\ntry:\n    await client.stop()\nexcept* Exception as eg:\n    for exc in eg.exceptions:\n        logging.warning(\"stop() sub-failure: %r\", exc)\n    await client.force_stop()","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    await client.stop()\nexcept ExceptionGroup as eg:\n    for exc in eg.exceptions:\n        logging.warning(\"stop() sub-failure: %r\", exc)\n    await client.force_stop()","preventionTips":["Use `except*` (Python 3.11+) to handle individual sub-failures","Fall back to force_stop() when graceful stop fails or times out","Avoid calling stop() on an already-dead client; check state first","Log session lifecycle to spot leaked sessions that break cleanup"],"tags":["python","shutdown","exception-group","cleanup"],"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"}