chenhg5/cc-connect · error
stdout pipe: %w
Error message
stdout pipe: %w
What it means
startRPC requests an stdout pipe for the pi RPC subprocess via cmd.StdoutPipe(); any OS error creating it is wrapped as 'stdout pipe: %w'. Like the stdin-pipe error, this is a near-impossible-in-practice OS-level failure that indicates resource exhaustion or exec package misuse.
Source
Thrown at agent/pi/session.go:203
cmd := exec.CommandContext(s.ctx, s.cmd, args...)
cmd.Dir = s.workDir
env := os.Environ()
if len(s.extraEnv) > 0 {
env = core.MergeEnv(env, s.extraEnv)
}
cmd.Env = env
stdinPipe, err := cmd.StdinPipe()
if err != nil {
return fmt.Errorf("stdin pipe: %w", err)
}
s.rpcStdin = stdinPipe
s.rpcCmd = cmd
stdout, err := cmd.StdoutPipe()
if err != nil {
return fmt.Errorf("stdout pipe: %w", err)
}
cmd.Stderr = &s.stderrBuf
prepareCmdForKill(cmd)
if err := cmd.Start(); err != nil {
return fmt.Errorf("start: %w", err)
}
s.wg.Add(1)
go s.readLoopRPC(stdout)
// Pi's RPC protocol does not push a "session" event on stdout — the only
// way to learn the session id is to send {"type":"get_state"} and parse
// the matching response in handleEvent. We probe immediately after spawn
// so that newPiSession's wait on rpcReady only unblocks once the id has
// been stored. readLoopRPC closes rpcReady as soon as sessionIDReady()
// flips to true (which happens after handleEvent processes the response),View on GitHub (pinned to 4000b2338a)
Solutions
- Kill leaked pi subprocesses and audit session teardown so stopped sessions release their pipes.
- Raise the nofile limit (`ulimit -n` or LimitNOFILE in systemd) and restart cc-connect.
- Check the wrapped cause for EMFILE/ENFILE and count open fds per process to find the leak.
- If it persists without resource pressure, verify no custom code calls cmd.Start()/Wait() on the same exec.Cmd before startRPC finishes wiring pipes.
Example fix
// before: sessions never stopped, fds leak
// after: ensure teardown
func (e *Engine) shutdown() {
for _, s := range e.sessions {
_ = s.Stop() // closes rpc pipes, reaps pi process
}
} Defensive patterns
Strategy: retry
Validate before calling
var lim syscall.Rlimit
syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim)
nFds, _ := countOpenFds(os.Getpid())
if nFds > int(float64(lim.Cur)*0.8) {
return fmt.Errorf("fd usage %d/%d too high; restart daemon or raise limit before starting pi", nFds, lim.Cur)
} Try / catch
sess, err := agent.StartSession(ctx, opts)
if err != nil && strings.Contains(err.Error(), "stdout pipe") {
log.Printf("stdout pipe allocation failed; likely fd exhaustion — check ulimit -n and leaked processes")
return fmt.Errorf("resource exhaustion starting pi: %w", err)
} Prevention
- Raise LimitNOFILE/ulimit -n for the cc-connect service.
- Ensure every started pi session is eventually Stop()'d so its pipes are released.
- Alert on fd-count trends; treat 80% of the limit as a warning threshold.
- Restart the daemon as a stopgap if descriptors leak, then fix the underlying leak.
When it happens
Trigger: startRPC (called from newPiSession) when cmd.StdoutPipe() fails — OS-level pipe/fd allocation failure, e.g. file descriptor limits (EMFILE/ENFILE) or memory pressure during pipe allocation.
Common situations: Same as stdin pipe failures: fd leaks from leaked pi processes, low LimitNOFILE in systemd/containers, fork bombs or runaway session loops exhausting descriptors.
Related errors
- stdin pipe: %w
- claudeSession: stdin pipe: %w
- claudeSession: stdout pipe: %w
- codex app-server stdin pipe: %w
- codex app-server stdout pipe: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/0a2ad0e826c291da.
Report an issue: GitHub.