chenhg5/cc-connect · error
read stdout: %w
Error message
read stdout: %w
What it means
The cursor agent session's stdout reader loop hits a read error while scanning the CLI process's stdout. It is wrapped with `read stdout: %w` and delivered as a core.EventError on the session's events channel, so consumers see it as a session event rather than a Send() return error. This signals the pipe to the cursor process broke or the OS read failed mid-stream.
Source
Thrown at agent/cursor/session.go:221
line := scanner.Text()
if line == "" {
continue
}
slog.Debug("cursorSession: raw", "line", truncateStr(line, 500))
var raw map[string]any
if err := json.Unmarshal([]byte(line), &raw); err != nil {
slog.Debug("cursorSession: non-JSON line", "line", line)
continue
}
cs.handleEvent(raw)
}
if err := scanner.Err(); err != nil {
slog.Error("cursorSession: scanner error", "error", err)
evt := core.Event{Type: core.EventError, Error: fmt.Errorf("read stdout: %w", err)}
select {
case cs.events <- evt:
case <-cs.ctx.Done():
return
}
}
}
func (cs *cursorSession) handleEvent(raw map[string]any) {
eventType, _ := raw["type"].(string)
switch eventType {
case "system":
cs.handleSystem(raw)
case "user":
// User echo — nothing to do
View on GitHub (pinned to 4000b2338a)
Solutions
- Read the wrapped inner error and the session's stderr/log output to find why the cursor process died
- Re-create the session (start a new one) since the stdout stream is unrecoverable after a scanner error
- Check the cursor CLI version and upgrade if the crash is a known bug
- Verify system resources (memory, disk, fd limits) if the child process is being killed
Example fix
// before: caller treats Send success as guarantee of completion
if err := sess.Send(prompt, id, nil, nil); err == nil { /* assume done */ }
// after: also consume events for the terminal error
go func() {
for evt := range sess.Events() {
if evt.Type == core.EventError {
log.Printf("cursor stream failed: %v", evt.Error)
// recreate session / notify user
}
}
}() Defensive patterns
Strategy: try-catch
Validate before calling
// ensure the cursor CLI is healthy before opening a session
if _, err := exec.LookPath("cursor-agent"); err != nil { return fmt.Errorf("cursor CLI unavailable: %w", err) } Try / catch
for evt := range sess.Events() {
if evt.Type == core.EventError {
var inner error
if errors.Unwrap(evt.Error) != nil { inner = errors.Unwrap(evt.Error) }
log.Printf("stdout stream failed: %v (cause: %v)", evt.Error, inner)
// recreate session, notify user
break
}
} Prevention
- Keep the cursor CLI updated
- Monitor child process exits and fd/memory limits on the host
- Always consume the Events channel rather than assuming Send success means completion
When it happens
Trigger: Calling Send() on a cursor session starts the CLI process and readLoop scans stdout; the scanner returns a non-EOF error (e.g. the cursor process crashed and closed the pipe, the OS returned EIO, or the process was killed) and readLoop emits this event.
Common situations: Cursor CLI crashing mid-response; user killing the process; OOM killer terminating the child; disk/pipe I/O errors; sending a prompt that makes the CLI abort abnormally.
Related errors
- read stdout: %w
- codex app-server connection closed: %w
- copilotSession: stdout pipe: %w
- read stdout: %w
- antigravitySession: stdout pipe: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/ae3533faebac3792.
Report an issue: GitHub.