chenhg5/cc-connect · error

copilot probe: stdin pipe: %w

Error message

copilot probe: stdin pipe: %w

What it means

newProbeSession builds a short-lived `copilot` subprocess (used by ListSessions and DeleteSession to inspect the CLI's session store) and wires os.Pipe-based stdin/stdout. This error wraps a StdinPipe() creation failure, which is rare and normally indicates resource exhaustion or the process being unable to create OS pipes. The function cancels its context before returning so no zombie process is left.

Source

Thrown at agent/copilot/copilot.go:218

type probeSnapshot struct {
	cmd  string
	workDir string
	env     []string
}

// newProbeSession spawns a copilot --headless --stdio probe process, starts a
// read loop, and returns a probeSession. Caller must call close() when done.
func newProbeSession(ctx context.Context, snapshot probeSnapshot) (*probeSession, error) {
	probeCtx, cancel := context.WithCancel(ctx)

	cmd := exec.CommandContext(probeCtx, snapshot.cmd, "--headless", "--stdio", "--no-auto-update")
	cmd.Dir = snapshot.workDir
	cmd.Env = snapshot.env

	stdin, err := cmd.StdinPipe()
	if err != nil {
		cancel()
		return nil, fmt.Errorf("copilot probe: stdin pipe: %w", err)
	}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		cancel()
		return nil, fmt.Errorf("copilot probe: stdout pipe: %w", err)
	}
	cmd.Stderr = io.Discard

	if err := cmd.Start(); err != nil {
		cancel()
		return nil, fmt.Errorf("copilot probe: start: %w", err)
	}

	rpc := newRPCClient(stdin)
	reader := newLSPReader(stdout)
	done := make(chan struct{})

	go func() {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Raise the file-descriptor limit: `ulimit -n 4096` or systemd LimitNOFILE=4096
  2. Check for fd leaks in the running process: `ls /proc/<pid>/fd | wc -l` and restart if it is near the limit
  3. Audit container limits (docker `--ulimit nofile=...`, k8s securityContext/rlimits)
  4. Reduce concurrent ListSessions/DeleteSession calls; retry the operation after freeing descriptors

Example fix

// before: probe fails under fd pressure
sessions, err := agent.ListSessions(ctx)
// after: pre-check fd headroom
if countOpenFDs(os.Getpid()) > softFDLimit() {
    log.Fatalf("too many open fds; raise ulimit -n before listing copilot sessions")
}
sessions, err := agent.ListSessions(ctx)
Defensive patterns

Strategy: try-catch

Validate before calling

n := countOpenFDs(os.Getpid())
var l syscall.Rlimit
syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
if uint64(n) > l.Cur-64 { return errors.New("fd headroom too low for copilot probe; raise ulimit -n") }

Try / catch

sessions, err := agent.ListSessions(ctx)
if err != nil && strings.Contains(err.Error(), "stdin pipe") {
    // resource exhaustion: free descriptors, then retry once
    runtime.GC()
    sessions, err = agent.ListSessions(ctx)
}

Prevention

When it happens

Trigger: cmd.StdinPipe() returns err inside newProbeSession, invoked from ListSessions or DeleteSession: OS-level pipe/file-descriptor exhaustion (ulimit -n), process resource limits in containers, or an out-of-memory condition in the parent.

Common situations: Long-running cc-connect leaking file descriptors until EMFILE; containers with very low RLIMIT_NOFILE; fork/proc limits hit after many concurrent probes; kernel pressure on hosts with thousands of connections.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/98918a6d64092c83. Report an issue: GitHub.