chenhg5/cc-connect · error

read: %w

Error message

read: %w

What it means

In the steady-state message loop, conn.ReadMessage failed while reading the next WebSocket frame; the error is wrapped as 'read: %w'. This terminates runConnection for this attempt and connectLoop reconnects. Any successfully-read but malformed JSON frames are only logged and skipped — this error is specifically a transport-level read failure.

Source

Thrown at platform/wecom/websocket.go:271

	slog.Info("wecom-ws: subscribed successfully", "bot_id", p.botID)
	p.missedPong.Store(0)

	// Start heartbeat goroutine
	heartCtx, heartCancel := context.WithCancel(p.ctx)
	defer heartCancel()
	go p.heartbeat(heartCtx, conn)

	// Read loop
	for {
		select {
		case <-p.ctx.Done():
			return p.ctx.Err()
		default:
		}

		_, raw, err := conn.ReadMessage()
		if err != nil {
			return fmt.Errorf("read: %w", err)
		}

		var frame wsFrame
		if err := json.Unmarshal(raw, &frame); err != nil {
			slog.Warn("wecom-ws: invalid json", "error", err)
			continue
		}

		p.handleFrame(frame)
	}
}

// handleFrame dispatches incoming frames by cmd or req_id prefix.
func (p *WSPlatform) handleFrame(frame wsFrame) {
	switch frame.Cmd {
	case "aibot_msg_callback":
		p.handleMsgCallback(frame)
	case "aibot_event_callback":

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Confirm heartbeat/pong keepalive is functioning (missedPong resets) — frequent reads errors on idle links indicate keepalive issues.
  2. Check the wrapped cause: 'close 1006' = abnormal close (network); clean close codes point to server-initiated disconnect.
  3. Rely on connectLoop automatic reconnection; alert only on persistent failure.
  4. Investigate NAT/load-balancer idle timeouts if drops occur after long silence.

Example fix

null
Defensive patterns

Strategy: retry

Validate before calling

if time.Since(p.lastPong) > pongTimeout { forceReconnect() } // detect half-open connections before reads fail

Type guard

null

Try / catch

err := platform.Start(ctx)
if err != nil && strings.Contains(err.Error(), "read:") {
	// transport drop; connectLoop reconnects — only alert if persistent
	if consecutiveFailures > threshold { alert() }
}

Prevention

When it happens

Trigger: Server closes the connection (close frame, EOF), network drops mid-frame, read deadline/pong timeout expires, or p.ctx cancellation interrupting the read.

Common situations: Idle connection reaped by a load balancer (mitigated by the heartbeat/pong mechanism); WeCom server maintenance restart; laptop sleep/network switch; proxy closing long-lived websocket connections.

Related errors


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