chenhg5/cc-connect · error

acp: probe stdout pipe: %w

Error message

acp: probe stdout pipe: %w

What it means

Same failure family as error 27 but on the output side: probeSpawn's cmd.StdoutPipe() call failed while preparing to launch the ACP agent for a ListSessions probe. It indicates an OS-level pipe allocation failure (fd exhaustion) before the process starts; ListSessions aborts with this error.

Source

Thrown at agent/acp/list_sessions.go:81

	UpdatedAt string `json:"updatedAt,omitempty"`
}

// probeSpawn launches `<cmd> <args...>`, sets up a JSON-RPC transport
// and starts its readLoop. The caller owns the returned `teardown`
// func and must invoke it to reap the child process.
func (a *Agent) probeSpawn(ctx context.Context, cwd string) (*transport, *bytes.Buffer, func(), error) {
	allArgs := append(append([]string{}, a.cliExtraArgs...), a.args...)
	cmd := exec.CommandContext(ctx, a.cmd, allArgs...)
	cmd.Dir = cwd
	cmd.Env = core.MergeEnv(os.Environ(), a.extraEnv)

	stdin, err := cmd.StdinPipe()
	if err != nil {
		return nil, nil, nil, fmt.Errorf("acp: probe stdin pipe: %w", err)
	}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, nil, nil, fmt.Errorf("acp: probe stdout pipe: %w", err)
	}
	var stderrBuf bytes.Buffer
	cmd.Stderr = io.MultiWriter(&stderrBuf)

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

	// The server-request handler needs to reference `tr` itself in order
	// to respondError; declare via var so the closure captures the
	// variable (which is assigned to a *transport below) rather than an
	// uninitialised copy.
	var tr *transport
	tr = newTransport(stdout, stdin,
		func(method string, _ json.RawMessage) {
			slog.Debug("acp-probe: notification", "method", method)
		},
		func(_ string, id json.RawMessage, _ json.RawMessage) {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Raise the fd limit (ulimit -n / systemd LimitNOFILE) and restart the daemon.
  2. Audit for leaked fds (`ls /proc/<pid>/fd | wc -l`) and fix or restart the leaking component.
  3. Serialize or reduce concurrent probeSpawn/ListSessions calls.
  4. Increase container nofile/pipe limits if running under Docker/Kubernetes.

Example fix

// before
$ ulimit -n
256
// after
$ ulimit -n 65536   # or systemd LimitNOFILE=65536
Defensive patterns

Strategy: retry

Validate before calling

var lim syscall.Rlimit
syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim)
if lim.Cur < 2048 {
    return errors.New("fd limit too low: StdoutPipe allocation may fail during acp probe")
}

Try / catch

if err != nil && strings.Contains(err.Error(), "probe stdout pipe") {
    slog.Warn("acp: stdout pipe allocation failed; retrying with backoff", "err", err)
    select {
    case <-time.After(backoff):
    case <-ctx.Done():
        return ctx.Err()
    }
    // retry ListSessions
}

Prevention

When it happens

Trigger: cmd.StdoutPipe() returns an error in probeSpawn — file-descriptor exhaustion (too many open fds), pipe allocation limits hit, or OS resource pressure after many concurrent agent probes.

Common situations: Daemons with fd leaks; low ulimit -n; containers with restrictive resource limits; parallel session listing against many agents.

Related errors


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