{"record":{"id":"7a57c301dee38856","repo":"github/copilot-sdk","slug":"cli-process-exited-w","errorCode":null,"errorMessage":"CLI process exited: %w","messagePattern":"CLI process exited: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"go/client.go","lineNumber":2408,"sourceCode":"// 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.\n\t\treturn nil\n\t}","sourceCodeStart":2390,"sourceCodeEnd":2426,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/go/client.go#L2390-L2426","documentation":"The no-stderr variant of the process-death error: the CLI process Wait() returned an error but nothing was captured on stderr, so the client reports only 'CLI process exited: <waitErr>'. The wrapped wait error (exit status) is the only diagnostic available.","triggerScenarios":"The CLI process exits with a non-zero status while producing no stderr output — e.g. killed by a signal, OOM-killed, or exiting via os.Exit with a non-zero code.","commonSituations":"OOM killer terminating the process (exit 137/SIGKILL), external scripts or supervisors killing it, silent fatal exits from the CLI binary.","solutions":["Decode the wrapped exit status: 137/SIGKILL usually means OOM — reduce workload or increase memory.","Check OS logs (dmesg, journalctl) for kill events around the crash time.","Enable the CLI's own logging (file-based) since stderr was empty.","Add restart-on-death logic around the client lifecycle."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"_, err := client.RPC.Call(ctx, \"method\", args)\nif err != nil {\n    var pe *os.SyscallError\n    if strings.Contains(err.Error(), \"CLI process exited\") {\n        // empty stderr: check wrapped exit status / dmesg for signal kills\n        log.Errorf(\"CLI died silently: %v\", err)\n    }\n    return err\n}","preventionTips":["Decode the wrapped exit status: 137/SIGKILL implies OOM or external kill.","Check dmesg/journalctl for silent kill events.","Configure the CLI to log to a file so crashes leave a trace even without stderr.","Add restart-on-death supervision around the client."],"tags":["process","crash","process-death","signal"],"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"}