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

  1. 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
  2. Check whether the claude process is still alive (`ps -p <pid>`); if dead, treat as a session crash and recreate via StartSession
  3. Treat the emitted EventError as terminal: close/reopen the session rather than retrying Send on the dead pipe
  4. 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

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


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