chenhg5/cc-connect · error

waiting for hello: %w

Error message

waiting for hello: %w

What it means

Returned by waitForHello when reading the first WebSocket frame fails before the Hello (op 10) handshake completes. The connection was established but closed or errored within the 15s deadline — network drop, server-side rejection, or premature close.

Source

Thrown at platform/qqbot/qqbot.go:723

		return "", fmt.Errorf("empty gateway URL in response")
	}
	return result.URL, nil
}

type wsPayload struct {
	Op int             `json:"op"`
	D  json.RawMessage `json:"d,omitempty"`
	S  *int64          `json:"s,omitempty"`
	T  string          `json:"t,omitempty"`
}

func (p *Platform) waitForHello(conn *websocket.Conn) error {
	_ = conn.SetReadDeadline(time.Now().Add(15 * time.Second))
	defer func() { _ = conn.SetReadDeadline(time.Time{}) }()

	var msg wsPayload
	if err := conn.ReadJSON(&msg); err != nil {
		return fmt.Errorf("waiting for hello: %w", err)
	}
	if msg.Op != opHello {
		return fmt.Errorf("expected op 10 (Hello), got op %d", msg.Op)
	}

	var hello struct {
		HeartbeatInterval int `json:"heartbeat_interval"`
	}
	if err := json.Unmarshal(msg.D, &hello); err != nil {
		slog.Warn("qqbot: failed to parse Hello payload", "error", err)
	}
	if hello.HeartbeatInterval > 0 {
		p.heartbeatMs = hello.HeartbeatInterval
	} else {
		p.heartbeatMs = 41250 // sane default
	}
	p.heartbeatOK.Store(true)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Retry the whole connect flow with backoff — this is often transient
  2. Check the QQ bot app status in the open-platform console (sandbox vs production, banned state)
  3. Increase the 15s hello deadline on slow networks
  4. Ensure only one instance of the bot is connected with the same credentials (QQ may drop duplicates)

Example fix

// before
_ = conn.SetReadDeadline(time.Now().Add(15 * time.Second))
// after
_ = conn.SetReadDeadline(time.Now().Add(30 * time.Second)) // slower networks
Defensive patterns

Strategy: retry

Validate before calling

// pre-check: ensure no duplicate bot instance holds the session
// and credentials were validated via a REST call before dialing

Try / catch

if err := p.waitForHello(conn); err != nil {
    var netErr net.Error
    if errors.As(err, &netErr) && netErr.Timeout() {
        return retryConnect() // transient, backoff
    }
    return err
}

Prevention

When it happens

Trigger: conn.ReadJSON in waitForHello errors: server closes the connection immediately after dial (bad auth at WS layer), read deadline of 15s expires, or network interruption.

Common situations: QQ rejects the connection right after dial because the app is offline/banned; slow network exceeding the 15s deadline; LB/proxy killing idle WS connections.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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