github/copilot-sdk · warning · ExceptionGroup

errors during CopilotClient.stop()

Error message

errors during CopilotClient.stop()

What it means

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.

Solutions

  1. Unpack the group: `except*` (3.11+) or iterate `e.exceptions` to see each failure.
  2. Call `await client.force_stop()` if graceful stop fails or hangs — it skips graceful cleanup.
  3. Inspect per-session health before stopping; close/abort problem sessions individually first.
  4. Upgrade the CLI/library if the failures point to known shutdown bugs.

Example fix

// before
await client.stop()
// after
try:
    await client.stop()
except* Exception as eg:
    for exc in eg.exceptions:
        logging.warning("stop() sub-failure: %r", exc)
    await client.force_stop()
Defensive patterns

Strategy: try-catch

Try / catch

try:
    await client.stop()
except ExceptionGroup as eg:
    for exc in eg.exceptions:
        logging.warning("stop() sub-failure: %r", exc)
    await client.force_stop()

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/dc92cb66b2b201fa. Report an issue: GitHub.

Appendix: source

Thrown at python/copilot/client.py:2175

                        )
                    except subprocess.TimeoutExpired as e:
                        errors.append(
                            StopError(
                                message=(
                                    f"Timed out waiting for CLI process to exit after kill: {e}"
                                )
                            )
                        )
            if self._process is self._cli_process:
                self._process = None
            self._cli_process = None

        self._state = "disconnected"
        if not self._is_external_server:
            self._runtime_port = None

        if errors:
            raise ExceptionGroup("errors during CopilotClient.stop()", errors)

    async def force_stop(self) -> None:
        """
        Forcefully stop the CLI server without graceful cleanup.

        Use this when :meth:`stop` fails or takes too long. This method:
        - Clears all sessions immediately without destroying them
        - Force closes the connection (closes the underlying transport)
        - Kills the CLI process (if spawned by this client)

        Example:
            >>> # If normal stop hangs, force stop
            >>> try:
            ...     await asyncio.wait_for(client.stop(), timeout=5.0)
            ... except asyncio.TimeoutError:
            ...     await client.force_stop()
        """
        # Clear sessions immediately without trying to destroy them

View on GitHub (pinned to cd8cf15dc3)