chenhg5/cc-connect · error
acp: probe stdin pipe: %w
Error message
acp: probe stdin pipe: %w
What it means
probeSpawn (agent/acp/list_sessions.go) launches the ACP agent briefly over stdio to enumerate existing sessions. This error occurs when os/exec's StdinPipe() fails, before the process starts — an OS-level pipe allocation failure, not an agent problem. ListSessions propagates it and aborts the listing.
Source
Thrown at agent/acp/list_sessions.go:77
type acpSessionListEntry struct {
SessionID string `json:"sessionId"`
Cwd string `json:"cwd"`
Title string `json:"title,omitempty"`
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,View on GitHub (pinned to 4000b2338a)
Solutions
- Raise the file-descriptor limit: `ulimit -n 4096` or systemd LimitNOFILE=65536, then restart cc-connect.
- Check for fd leaks with `ls /proc/<pid>/fd | wc -l` and restart the daemon if the count is near the limit.
- Reduce concurrent ListSessions/agent spawn operations.
- If in a container, raise nofile limits in the container runtime configuration.
Example fix
// before (systemd unit) [Service] ExecStart=/usr/bin/cc-connect // after [Service] ExecStart=/usr/bin/cc-connect LimitNOFILE=65536
Defensive patterns
Strategy: retry
Validate before calling
// before spawning, ensure headroom for pipes/fds:
var lim syscall.Rlimit
syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim)
if lim.Cur < 1024 {
return errors.New("file descriptor limit too low for agent probes; raise ulimit -n")
} Try / catch
sessions, _, err := a.ListSessions(ctx)
if err != nil && strings.Contains(err.Error(), "probe stdin pipe") {
// fd exhaustion — wait and retry after limits/restart
slog.Warn("acp: probe pipe failed, retrying later", "err", err)
time.Sleep(backoff)
sessions, _, err = a.ListSessions(ctx)
} Prevention
- Raise ulimit -n / systemd LimitNOFILE on hosts running cc-connect
- Monitor open fd count of the daemon and restart on leaks
- Limit concurrency of session probes
- Set generous nofile limits in container runtimes
When it happens
Trigger: cmd.StdinPipe() returns an error inside probeSpawn during ListSessions — typically resource exhaustion: the process hit its file-descriptor limit (ulimit -n), or the OS refused new pipe allocations.
Common situations: Long-running daemons leaking file descriptors; low ulimit -n on servers; containers with small fd limits; spawning many concurrent ListSessions probes.
Related errors
- acp: probe stdout pipe: %w
- acp: probe start %s: %w
- claudeSession: stdin pipe: %w
- claudeSession: stdout pipe: %w
- stdin pipe: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/17f5bd94720ec1d8.
Report an issue: GitHub.