{"record":{"id":"17f5bd94720ec1d8","repo":"chenhg5/cc-connect","slug":"acp-probe-stdin-pipe-w","errorCode":null,"errorMessage":"acp: probe stdin pipe: %w","messagePattern":"acp: probe stdin pipe: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/acp/list_sessions.go","lineNumber":77,"sourceCode":"type acpSessionListEntry struct {\n\tSessionID string `json:\"sessionId\"`\n\tCwd       string `json:\"cwd\"`\n\tTitle     string `json:\"title,omitempty\"`\n\tUpdatedAt string `json:\"updatedAt,omitempty\"`\n}\n\n// probeSpawn launches `<cmd> <args...>`, sets up a JSON-RPC transport\n// and starts its readLoop. The caller owns the returned `teardown`\n// func and must invoke it to reap the child process.\nfunc (a *Agent) probeSpawn(ctx context.Context, cwd string) (*transport, *bytes.Buffer, func(), error) {\n\tallArgs := append(append([]string{}, a.cliExtraArgs...), a.args...)\n\tcmd := exec.CommandContext(ctx, a.cmd, allArgs...)\n\tcmd.Dir = cwd\n\tcmd.Env = core.MergeEnv(os.Environ(), a.extraEnv)\n\n\tstdin, err := cmd.StdinPipe()\n\tif err != nil {\n\t\treturn nil, nil, nil, fmt.Errorf(\"acp: probe stdin pipe: %w\", err)\n\t}\n\tstdout, err := cmd.StdoutPipe()\n\tif err != nil {\n\t\treturn nil, nil, nil, fmt.Errorf(\"acp: probe stdout pipe: %w\", err)\n\t}\n\tvar stderrBuf bytes.Buffer\n\tcmd.Stderr = io.MultiWriter(&stderrBuf)\n\n\tif err := cmd.Start(); err != nil {\n\t\treturn nil, nil, nil, fmt.Errorf(\"acp: probe start %s: %w\", a.cmd, err)\n\t}\n\n\t// The server-request handler needs to reference `tr` itself in order\n\t// to respondError; declare via var so the closure captures the\n\t// variable (which is assigned to a *transport below) rather than an\n\t// uninitialised copy.\n\tvar tr *transport\n\ttr = newTransport(stdout, stdin,","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/acp/list_sessions.go#L59-L95","documentation":"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.","triggerScenarios":"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.","commonSituations":"Long-running daemons leaking file descriptors; low ulimit -n on servers; containers with small fd limits; spawning many concurrent ListSessions probes.","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."],"exampleFix":"// before (systemd unit)\n[Service]\nExecStart=/usr/bin/cc-connect\n// after\n[Service]\nExecStart=/usr/bin/cc-connect\nLimitNOFILE=65536","handlingStrategy":"retry","validationCode":"// before spawning, ensure headroom for pipes/fds:\nvar lim syscall.Rlimit\nsyscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim)\nif lim.Cur < 1024 {\n    return errors.New(\"file descriptor limit too low for agent probes; raise ulimit -n\")\n}","typeGuard":null,"tryCatchPattern":"sessions, _, err := a.ListSessions(ctx)\nif err != nil && strings.Contains(err.Error(), \"probe stdin pipe\") {\n    // fd exhaustion — wait and retry after limits/restart\n    slog.Warn(\"acp: probe pipe failed, retrying later\", \"err\", err)\n    time.Sleep(backoff)\n    sessions, _, err = a.ListSessions(ctx)\n}","preventionTips":["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"],"tags":["acp","os","file-descriptors","process-spawn"],"backgroundTag":"resource-exhaustion","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}