chenhg5/cc-connect · error
piSession: write stdin: %w
Error message
piSession: write stdin: %w
What it means
This error is produced by writeRPCCommand in agent/pi/session.go when writing a JSON-RPC command line to the stdin of the persistent pi RPC child process fails. The wrapped os.ErrClosed or broken-pipe error is included via %w, so the underlying cause is always the child's stdin pipe. The pi adapter keeps one long-lived RPC process per session and serializes all stdin writes through rpcStdinMu; this error means that channel to the child is unusable.
Source
Thrown at agent/pi/session.go:462
return nil
}
// writeRPCCommand marshals cmd as a single JSONL line and writes it to the
// RPC process's stdin under rpcStdinMu. Used by both sendRPC (for "prompt"
// commands during a turn) and startRPC (for the startup "get_state" probe
// that fetches the session id before callers are released).
func (s *piSession) writeRPCCommand(cmd map[string]any) error {
b, err := json.Marshal(cmd)
if err != nil {
return fmt.Errorf("piSession: marshal command: %w", err)
}
b = append(b, '\n')
s.rpcStdinMu.Lock()
_, err = s.rpcStdin.Write(b)
s.rpcStdinMu.Unlock()
if err != nil {
return fmt.Errorf("piSession: write stdin: %w", err)
}
return nil
}
// sendRPC writes a JSON "prompt" command to the persistent RPC process stdin.
// Events are read asynchronously by readLoopRPC, including agent_end which
// triggers EventResult.
//
// Issue #1723: image paths are embedded into the message text as
// @<path> references (pi's standard mechanism, parsed the same way as in
// json mode). The rpc stdin pipe doesn't crash on NUL bytes, but the
// model still needs to load the images from disk — embedding raw bytes
// in the message field would give the model text-shaped garbage instead
// of a real visual input.
//
// Issue #1767: filePaths (non-image attachments) are NOT @<path>'d.
// pi's processFileArguments would inline their full UTF-8 contents into
// the message text the model sees; we append a plain "Files savedView on GitHub (pinned to 4000b2338a)
Solutions
- Check the wrapped cause with errors.Is(err, os.ErrClosed) / io.ErrClosedPipe to confirm the child process is gone
- Recreate the pi session (start a new RPC process) instead of retrying the write
- Log/inspect why the pi process exited (stderr, exit status) before restarting
- Guard Send with a session-alive check so callers get a clearer 'session closed' error
Example fix
// before
if err := session.Send(ctx, msg); err != nil {
return fmt.Errorf("send failed: %w", err)
}
// after
if err := session.Send(ctx, msg); err != nil {
if errors.Is(err, os.ErrClosed) || errors.Is(err, io.ErrClosedPipe) {
session, err = pi.NewSession(opts) // restart RPC process
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go: check liveness before writing
if !sessionAlive() {
return errors.New("pi session closed")
} Type guard
func isPipeClosed(err error) bool {
return errors.Is(err, os.ErrClosed) || errors.Is(err, io.ErrClosedPipe) || errors.Is(err, syscall.EPIPE)
} Try / catch
if err := writeRPCCommand(cmd); err != nil {
if isPipeClosed(err) {
// child process is gone; restart session and resend once
return restartAndRetry(cmd)
}
return err
} Prevention
- Check session/process liveness before each send
- Resolve pending turns before calling Close/Stop
- Monitor child exit status so you never write to a dead pipe
- Retry once with a fresh session on pipe-closed errors
When it happens
Trigger: Calling Send (via sendRPC) or starting the session (via startRPC) after the pi process has exited or its stdin pipe was closed; writes racing with Close(); the child crashing mid-session so the pipe is broken.
Common situations: The pi CLI binary crashed or was killed (OOM, signal) while the session object still looked alive; a turn was cancelled and teardown closed stdin while a send was in flight; a stale session reused after process exit.
Related errors
- piSession: write extension_ui_response: %w
- antigravitySession: stdout pipe: %w
- antigravitySession: start: %w
- write hook response: %w
- write stdin: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/3e549602928153bc.
Report an issue: GitHub.