github/copilot-sdk · error · RuntimeError
str(e)
Error message
str(e)
What it means
When CopilotClient.start() fails, the library logs the failure, sets internal state to 'error', and re-raises as `RuntimeError(str(e)) from None` — deliberately suppressing the original traceback/exception type. Developers see only the stringified underlying error, which can make the root cause (process spawn failure, binary missing, handshake timeout, etc.) harder to trace.
Solutions
- Read the RuntimeError message — it contains the underlying cause string.
- Enable logging at WARNING/DEBUG for 'CopilotClient.start failed' (log_timing output includes exc_info).
- Verify the CLI binary path/availability manually before calling start().
- Catch RuntimeError around start() and, if needed, inspect the full chain via logs since `from None` hides the original exception.
Example fix
// before
await client.start() # bare RuntimeError, no chained traceback
// after
try:
await client.start()
except RuntimeError as e:
logging.getLogger(__name__).error("Copilot startup failed: %s", e)
raise Defensive patterns
Strategy: try-catch
Validate before calling
import shutil
if shutil.which(cli_path) is None:
raise FileNotFoundError(f"Copilot CLI not found: {cli_path}") Try / catch
try:
await client.start()
except RuntimeError as e:
logger.error("CopilotClient.start failed: %s", e)
raise StartupError(str(e)) from e Prevention
- Verify the CLI binary exists and is executable before start()
- Enable library logging (WARNING+) to capture the underlying cause
- Pin a compatible CLI version in your deployment
- Wrap start() in app-level startup checks that fail with clear messages
When it happens
Trigger: Any failure inside start(): the Copilot CLI subprocess fails to spawn or exits during startup, the handshake/connection to the CLI fails, or an expected startup exception type (the `except` clause above the generic handler) is raised.
Common situations: Copilot CLI binary not installed or not on PATH; wrong CLI path configured; permission denied executing the binary; CLI crashes immediately due to bad arguments or version mismatch.
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
- {process exit error from _get_process_exit_error()}
- Failed to delete session
- Failed to set foreground session
- Process not started or stdout not available
- CLI process exited before announcing port
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/54a1e161900f668d.
Report an issue: GitHub.
Appendix: source
Thrown at python/copilot/client.py:2011
self._state = "connected"
log_timing(
logger,
logging.DEBUG,
"CopilotClient.start complete",
start_time,
)
except ProcessExitedError as e:
# Process exited with error - reraise as RuntimeError with stderr
self._state = "error"
log_timing(
logger,
logging.WARNING,
"CopilotClient.start failed",
start_time,
exc_info=True,
)
raise RuntimeError(str(e)) from None
except Exception as e:
self._state = "error"
log_timing(
logger,
logging.WARNING,
"CopilotClient.start failed",
start_time,
exc_info=True,
)
# Check if process exited and capture any remaining stderr
process = self._cli_process if self._cli_process is not None else self._process
if process and hasattr(process, "poll"):
if isinstance(e, BrokenPipeError) and process.poll() is None:
try:
await asyncio.to_thread(process.wait, timeout=1.0)
except subprocess.TimeoutExpired:
pass
return_code = process.poll()View on GitHub (pinned to cd8cf15dc3)