chenhg5/cc-connect · critical
ws connect: %w
Error message
ws connect: %w
What it means
Returned by the QQ bot WebSocket connect step when websocket.DefaultDialer.Dial fails to establish a TCP+TLS connection to the gateway URL obtained from the QQ gateway API. The error wraps the underlying dial error (DNS failure, TLS handshake, timeout, refused connection). Platform startup aborts because the WS link is mandatory for receiving events.
Source
Thrown at platform/qqbot/qqbot.go:650
// WebSocket Gateway
// ---------------------------------------------------------------------------
func (p *Platform) connectGateway(ctx context.Context) error {
token, err := p.getAccessToken()
if err != nil {
return err
}
// Get gateway URL
gatewayURL, err := p.getGatewayURL(token)
if err != nil {
return err
}
// Connect WebSocket
conn, _, err := websocket.DefaultDialer.Dial(gatewayURL, nil)
if err != nil {
return fmt.Errorf("ws connect: %w", err)
}
p.wsMu.Lock()
p.wsConn = conn
p.wsMu.Unlock()
// Wait for Hello (op 10)
if err := p.waitForHello(conn); err != nil {
conn.Close()
return err
}
// Send Identify (op 2)
if err := p.sendIdentify(conn, token); err != nil {
conn.Close()
return err
}
View on GitHub (pinned to 4000b2338a)
Solutions
- Verify outbound network access: curl the gateway URL host from the same machine
- Check proxy env vars (HTTP_PROXY/HTTPS_PROXY) are correct if behind a proxy
- Re-check that getGatewayURL succeeded and the appid/secret are valid so a real gateway URL is returned
- Retry with backoff — gateway outages are usually transient
Example fix
// before
conn, _, err := websocket.DefaultDialer.Dial(gatewayURL, nil)
// after
dialer := websocket.DefaultDialer
dialer.HandshakeTimeout = 10 * time.Second
conn, _, err := dialer.Dial(gatewayURL, nil)
if err != nil {
return fmt.Errorf("ws connect: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
u, err := url.Parse(gatewayURL)
if err != nil || u.Scheme != "wss" && u.Scheme != "ws" {
return fmt.Errorf("bad gateway URL: %v", err)
} Try / catch
for attempt := 0; attempt < 5; attempt++ {
if err := connectWS(); err != nil {
if errors.Is(err, syscall.ECONNREFUSED) {
time.Sleep(backoff(attempt)); continue
}
return err
}
break
} Prevention
- Health-check outbound connectivity to QQ hosts before starting the bot
- Set an explicit dialer handshake timeout
- Monitor gateway URL fetch failures separately from dial failures
When it happens
Trigger: Dial(gatewayURL) fails: network down, DNS cannot resolve the gateway host, proxy/firewall blocks wss://, or the gateway URL from the API is malformed/unreachable.
Common situations: Running on an isolated server/CI without outbound HTTPS to QQ servers; corporate firewall blocking WebSocket upgrades; transient QQ gateway outage; wrong system proxy settings.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- qqbot: failed to connect gateway: %w
- wecom-ws: ack timeout
- read register_ack: %w
- cloud_web: websocket disconnected
- qq: ws connect failed (%s): %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/4e2dba31eec13299.
Report an issue: GitHub.