{"record":{"id":"a1f57b85f627070d","repo":"chenhg5/cc-connect","slug":"geminisession-stdout-pipe-w","errorCode":null,"errorMessage":"geminiSession: stdout pipe: %w","messagePattern":"geminiSession: stdout pipe: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/gemini/session.go","lineNumber":187,"sourceCode":"\t\t\tcancel()\n\t\t}\n\t}()\n\n\tslog.Debug(\"geminiSession: launching\", \"resume\", isResume, \"args\", core.RedactArgs(args))\n\tcmd := exec.CommandContext(ctx, gs.cmd, args...)\n\t// Set a short WaitDelay to ensure I/O goroutines don't block for long after the context is done\n\tcmd.WaitDelay = 1 * time.Second\n\tcmd.Dir = gs.workDir\n\tenv := os.Environ()\n\tif len(gs.extraEnv) > 0 {\n\t\tenv = core.MergeEnv(env, gs.extraEnv)\n\t}\n\tcmd.Env = env\n\tcmd.Stdin = strings.NewReader(fullPrompt)\n\n\tstdout, err := cmd.StdoutPipe()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"geminiSession: stdout pipe: %w\", err)\n\t}\n\n\tvar stderrBuf bytes.Buffer\n\tcmd.Stderr = &stderrBuf\n\n\tif err := cmd.Start(); err != nil {\n\t\treturn fmt.Errorf(\"geminiSession: start: %w\", err)\n\t}\n\n\tstarted = true\n\tgs.wg.Add(1)\n\tgo func() {\n\t\tdefer cancel()\n\t\tgs.readLoop(ctx, cmd, stdout, &stderrBuf, append(imageRefs, fileRefs...))\n\t}()\n\n\treturn nil\n}","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/gemini/session.go#L169-L205","documentation":"Send builds the exec.Cmd for the gemini CLI and calls StdoutPipe(); if the OS pipe cannot be created it wraps the error as `geminiSession: stdout pipe: %w` and aborts the send. This is a rare OS-level failure creating the unidirectional pipe for capturing CLI output.","triggerScenarios":"Calling Send when cmd.StdoutPipe() fails — typically fd exhaustion (too many open files) or an internal os/exec state problem (e.g. Stdout already set / command reused).","commonSituations":"Daemon leaking processes/fds over a long uptime hitting the RLIMIT_NOFILE limit; misconfigured ulimits in containers; reusing an exec.Cmd that already had StdoutPipe called.","solutions":["Check fd usage of the cc-connect process (`ls /proc/<pid>/fd | wc -l`) and raise the limit (`ulimit -n` / LimitNOFILE in systemd)","Look for leaked gemini child processes or unclosed sessions causing fd exhaustion","Restart the daemon to clear leaked descriptors","Ensure each exec.Cmd is used once (fresh Cmd per Send)"],"exampleFix":"// before\n[Service]\nExecStart=/usr/local/bin/cc-connect\n// after\n[Service]\nLimitNOFILE=65536\nExecStart=/usr/local/bin/cc-connect","handlingStrategy":"retry","validationCode":"f, err := os.Open(os.DevNull); if err == nil { f.Close() } else { return fmt.Errorf(\"fd exhaustion likely: %w\", err) }","typeGuard":null,"tryCatchPattern":"if err := sess.Send(prompt, id, nil, nil); err != nil && strings.Contains(err.Error(), \"stdout pipe\") {\n  time.Sleep(500 * time.Millisecond)\n  return sess.Send(prompt, id, nil, nil) // retry once; persistent failure => fd leak\n}","preventionTips":["Raise RLIMIT_NOFILE / systemd LimitNOFILE for long-running daemons","Watch for leaked gemini child processes and close idle sessions","Restart the daemon periodically or on fd-count alerts"],"tags":["process","pipe","file-descriptors"],"backgroundTag":"file-open-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}