chenhg5/cc-connect · error
read stdout: %w
Error message
read stdout: %w
What it means
handleReadLoopScanErr fires when the bufio.Scanner reading the claude process's stdout returns a non-EOF error. The raw scanner error is wrapped as 'read stdout: %w' and emitted as a core.EventError. This means the stdout stream broke unexpectedly mid-session (process died, pipe closed, or — commonly — bufio.Scanner's 64KB default token limit exceeded).
Source
Thrown at agent/claudecode/session.go:587
close(cs.events)
close(cs.done)
}
func (cs *claudeSession) handleReadLoopScanErr(err error, waitDone <-chan struct{}) {
if err == nil {
return
}
select {
case <-cs.ctx.Done():
return
case <-waitDone:
return
default:
}
slog.Error("claudeSession: 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 *claudeSession) handleReadLoopLine(line string) {
if line == "" {
return
}
var raw map[string]any
if err := json.Unmarshal([]byte(line), &raw); err != nil {
slog.Debug("claudeSession: non-JSON line", "line", line)
return
}
View on GitHub (pinned to 4000b2338a)
Solutions
- If the wrapped error is bufio.ErrTooLong, enlarge the scanner buffer with scanner.Buffer(make([]byte, 0, 64*1024), 10*1024*1024) in readLoop before scanning
- Check whether the claude process is still alive (`ps -p <pid>`); if dead, treat as a session crash and recreate via StartSession
- Treat the emitted EventError as terminal: close/reopen the session rather than retrying Send on the dead pipe
- If it reproduces with huge outputs, reduce max output size in agent settings or split requests
Example fix
// before scanner := bufio.NewScanner(stdout) // after scanner := bufio.NewScanner(stdout) scanner.Buffer(make([]byte, 0, 64*1024), 10*1024*1024)
Defensive patterns
Strategy: fallback
Validate before calling
// no pre-call validation possible; mitigate by raising the scanner limit in readLoop scanner := bufio.NewScanner(stdout) scanner.Buffer(make([]byte, 0, 64*1024), 10*1024*1024) // allow 10MB lines
Try / catch
for evt := range sess.Events() {
if evt.Type == core.EventError && strings.Contains(evt.Error.Error(), "read stdout") {
if errors.Is(evt.Error, bufio.ErrTooLong) {
// oversized line: upgrade scanner buffer / limit output size
}
sess = recreateSession() // stream is broken; session unusable
}
} Prevention
- Always enlarge bufio.Scanner buffers when parsing LLM JSON-lines output
- Monitor for CLI crashes and auto-recreate sessions on EventError
- Limit per-response output size in agent settings to keep lines under buffer limits
- Check disk/pipe health if I/O errors repeat on the same host
When it happens
Trigger: readLoop's scanner hits Scan() error: the claude process died and the pipe broke, the OS returned an I/O error, or a single stdout line exceeded bufio.MaxScanTokenSize (64KB) producing bufio.ErrTooLong.
Common situations: Very large assistant messages / huge tool outputs from Claude Code producing one JSON line over 64KB; abrupt CLI crash mid-stream; session killed while a line was being read.
Related errors
- write stdin: %w
- codex app-server stdin pipe: %w
- codex app-server stdout pipe: %w
- codex app-server stderr pipe: %w
- read stdout: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/28ab2eecf4fd42ce.
Report an issue: GitHub.