github/copilot-sdk · critical
CLI process exited: \nstderr
Error message
CLI process exited: %w\nstderr: %s
What it means
The monitoring goroutine waits on the CLI process and, when Wait() returns an error (non-zero exit or failed wait), stores 'CLI process exited: <err>' with the captured stderr appended. This error is surfaced through the client's processError channel to RPC callers whose in-flight requests are then failed. It means the CLI server process died unexpectedly during operation.
Solutions
- Read the embedded stderr for the crash cause (panic trace, OOM message).
- Check system logs for OOM-killer events if stderr is empty but the exit code is 137.
- Upgrade the CLI/library pair; a known crash may be fixed in a newer version.
- Wrap RPC calls with retry-on-process-death logic that restarts the client.
Example fix
// before
resp, err := client.RPC.Call(ctx, "method", args)
// after
resp, err := client.RPC.Call(ctx, "method", args)
if err != nil && strings.Contains(err.Error(), "CLI process exited") {
client = newClient(); client.Start(ctx) // restart and retry
} Defensive patterns
Strategy: retry
Try / catch
_, err := client.RPC.Call(ctx, "method", args)
if err != nil && strings.Contains(err.Error(), "CLI process exited") {
client = NewClient(cfg)
if err := client.Start(restartCtx); err != nil { return err }
return client.RPC.Call(ctx, "method", args) // one retry after restart
} Prevention
- Parse the embedded stderr for the crash cause before retrying.
- Monitor for OOM kills (exit 137) and size the environment accordingly.
- Keep CLI and library versions matched to avoid known crash bugs.
- Implement automatic client restart on process death for long-running services.
When it happens
Trigger: The CLI server process crashes or exits non-zero while the client is active; the monitor captures waitErr plus any stderr output into processError, delivered via SetProcessDone/processErrorPtr.
Common situations: CLI running out of memory, hitting an internal panic, being OOM-killed by the OS, or exiting due to a fatal runtime error mid-session.
Related errors
- CLI process exited
- CLI process exited unexpectedly. stderr
- CLI process exited unexpectedly
- workingDirectory is not supported with…
- env is not supported with RuntimeConnection.forInProcess()…
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/701623c3bda96ff6.
Report an issue: GitHub.
Appendix: source
Thrown at go/client.go:2406
// error value, so goroutines from previous processes can't overwrite the
// current one. Closing the channel synchronizes with readers, guaranteeing
// they see the final processError value.
func (c *Client) monitorProcess() {
done := make(chan struct{})
c.processDone = done
proc := c.process
c.osProcess.Store(proc.Process)
var processError error
c.processErrorPtr = &processError
go func() {
waitErr := proc.Wait()
var stderrOutput string
if buf, ok := proc.Stderr.(*truncbuffer.TruncBuffer); ok {
stderrOutput = strings.TrimSpace(buf.String())
}
if waitErr != nil {
if stderrOutput != "" {
processError = fmt.Errorf("CLI process exited: %w\nstderr: %s", waitErr, stderrOutput)
} else {
processError = fmt.Errorf("CLI process exited: %w", waitErr)
}
} else {
if stderrOutput != "" {
processError = fmt.Errorf("CLI process exited unexpectedly\nstderr: %s", stderrOutput)
} else {
processError = errors.New("CLI process exited unexpectedly")
}
}
close(done)
}()
}
// connectToServer establishes a connection to the server.
func (c *Client) connectToServer(ctx context.Context) error {
if c.useStdio || c.useInProcess {
// Already connected: stdio in startCLIServer, FFI streams in startInProcess.View on GitHub (pinned to cd8cf15dc3)