{"record":{"id":"701623c3bda96ff6","repo":"github/copilot-sdk","slug":"cli-process-exited-w-nstderr-s","errorCode":null,"errorMessage":"CLI process exited: %w\\nstderr: %s","messagePattern":"CLI process exited: %w\\\\nstderr: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"go/client.go","lineNumber":2406,"sourceCode":"// error value, so goroutines from previous processes can't overwrite the\n// current one. Closing the channel synchronizes with readers, guaranteeing\n// they see the final processError value.\nfunc (c *Client) monitorProcess() {\n\tdone := make(chan struct{})\n\tc.processDone = done\n\tproc := c.process\n\tc.osProcess.Store(proc.Process)\n\tvar processError error\n\tc.processErrorPtr = &processError\n\tgo func() {\n\t\twaitErr := proc.Wait()\n\t\tvar stderrOutput string\n\t\tif buf, ok := proc.Stderr.(*truncbuffer.TruncBuffer); ok {\n\t\t\tstderrOutput = strings.TrimSpace(buf.String())\n\t\t}\n\t\tif waitErr != nil {\n\t\t\tif stderrOutput != \"\" {\n\t\t\t\tprocessError = fmt.Errorf(\"CLI process exited: %w\\nstderr: %s\", waitErr, stderrOutput)\n\t\t\t} else {\n\t\t\t\tprocessError = fmt.Errorf(\"CLI process exited: %w\", waitErr)\n\t\t\t}\n\t\t} else {\n\t\t\tif stderrOutput != \"\" {\n\t\t\t\tprocessError = fmt.Errorf(\"CLI process exited unexpectedly\\nstderr: %s\", stderrOutput)\n\t\t\t} else {\n\t\t\t\tprocessError = errors.New(\"CLI process exited unexpectedly\")\n\t\t\t}\n\t\t}\n\t\tclose(done)\n\t}()\n}\n\n// connectToServer establishes a connection to the server.\nfunc (c *Client) connectToServer(ctx context.Context) error {\n\tif c.useStdio || c.useInProcess {\n\t\t// Already connected: stdio in startCLIServer, FFI streams in startInProcess.","sourceCodeStart":2388,"sourceCodeEnd":2424,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/go/client.go#L2388-L2424","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nresp, err := client.RPC.Call(ctx, \"method\", args)\n// after\nresp, err := client.RPC.Call(ctx, \"method\", args)\nif err != nil && strings.Contains(err.Error(), \"CLI process exited\") {\n    client = newClient(); client.Start(ctx) // restart and retry\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"_, err := client.RPC.Call(ctx, \"method\", args)\nif err != nil && strings.Contains(err.Error(), \"CLI process exited\") {\n    client = NewClient(cfg)\n    if err := client.Start(restartCtx); err != nil { return err }\n    return client.RPC.Call(ctx, \"method\", args) // one retry after restart\n}","preventionTips":["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."],"tags":["process","crash","process-death","rpc"],"backgroundTag":"process-exited-unexpectedly","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"}