chenhg5/cc-connect · error
geminiSession: stdout pipe: %w
Error message
geminiSession: stdout pipe: %w
What it means
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.
Source
Thrown at agent/gemini/session.go:187
cancel()
}
}()
slog.Debug("geminiSession: launching", "resume", isResume, "args", core.RedactArgs(args))
cmd := exec.CommandContext(ctx, gs.cmd, args...)
// Set a short WaitDelay to ensure I/O goroutines don't block for long after the context is done
cmd.WaitDelay = 1 * time.Second
cmd.Dir = gs.workDir
env := os.Environ()
if len(gs.extraEnv) > 0 {
env = core.MergeEnv(env, gs.extraEnv)
}
cmd.Env = env
cmd.Stdin = strings.NewReader(fullPrompt)
stdout, err := cmd.StdoutPipe()
if err != nil {
return fmt.Errorf("geminiSession: stdout pipe: %w", err)
}
var stderrBuf bytes.Buffer
cmd.Stderr = &stderrBuf
if err := cmd.Start(); err != nil {
return fmt.Errorf("geminiSession: start: %w", err)
}
started = true
gs.wg.Add(1)
go func() {
defer cancel()
gs.readLoop(ctx, cmd, stdout, &stderrBuf, append(imageRefs, fileRefs...))
}()
return nil
}View on GitHub (pinned to 4000b2338a)
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)
Example fix
// before [Service] ExecStart=/usr/local/bin/cc-connect // after [Service] LimitNOFILE=65536 ExecStart=/usr/local/bin/cc-connect
Defensive patterns
Strategy: retry
Validate before calling
f, err := os.Open(os.DevNull); if err == nil { f.Close() } else { return fmt.Errorf("fd exhaustion likely: %w", err) } Try / catch
if err := sess.Send(prompt, id, nil, nil); err != nil && strings.Contains(err.Error(), "stdout pipe") {
time.Sleep(500 * time.Millisecond)
return sess.Send(prompt, id, nil, nil) // retry once; persistent failure => fd leak
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- codex app-server stdin pipe: %w
- codex app-server stdout pipe: %w
- codex app-server stderr pipe: %w
- read stdout: %w
- %s write timed out
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/a1f57b85f627070d.
Report an issue: GitHub.