github/copilot-sdk · critical

CLI process exited unexpectedly

Error message

CLI process exited unexpectedly

What it means

The CLI subprocess terminated without the wait error indicating a normal exit, so the monitor goroutine records processError = "CLI process exited unexpectedly", optionally with captured stderr. This error is surfaced through processErrorPtr to the JSON-RPC client and to callers awaiting the process result.

Solutions

  1. Read the stderr attached to the error for the underlying cause
  2. Check dmesg/journal for OOM or signal kills and raise limits if needed
  3. Ensure the runtime binary matches the SDK version; reinstall/upgrade if mismatched
  4. Handle the processDone/processError channel in your app to restart the client gracefully
Defensive patterns

Strategy: try-catch

Try / catch

select {
case <-client.ProcessDone():
    if err := *client.ProcessError(); err != nil && strings.Contains(err.Error(), "exited unexpectedly") {
        log.Errorf("CLI crashed: %v", err)
        // restart client with backoff
    }
case <-ctx.Done():
}

Prevention

When it happens

Trigger: The CLI process crashes (non-zero, unexpected exit) while the client is running; wait() returns without a recognized exit-status error and stderr may or may not be available.

Common situations: Runtime crashes mid-session; OOM kills; signal termination (SIGKILL from supervisors); corrupt or incompatible runtime binaries; underlying native library faults in runtime.node.

Related errors


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

Appendix: source

Thrown at go/client.go:2414

	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.
		return nil
	}

	// Connect via TCP
	return c.connectViaTCP(ctx)
}

// connectViaTCP connects to the CLI server via TCP socket.

View on GitHub (pinned to cd8cf15dc3)