{"record":{"id":"43d96b4c148b964d","repo":"chenhg5/cc-connect","slug":"dial-w","errorCode":null,"errorMessage":"dial: %w","messagePattern":"dial: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/wecom/websocket.go","lineNumber":193,"sourceCode":"\t\tcase <-time.After(backoff):\n\t\tcase <-p.ctx.Done():\n\t\t\treturn\n\t\t}\n\n\t\tbackoff *= 2\n\t\tif backoff > wsMaxBackoff {\n\t\t\tbackoff = wsMaxBackoff\n\t\t}\n\t}\n}\n\n// runConnection dials, subscribes, and processes messages until disconnection.\nfunc (p *WSPlatform) runConnection() error {\n\tslog.Info(\"wecom-ws: connecting\", \"endpoint\", wsEndpoint)\n\n\tconn, _, err := websocket.DefaultDialer.DialContext(p.ctx, wsEndpoint, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dial: %w\", err)\n\t}\n\n\tp.mu.Lock()\n\tp.conn = conn\n\tp.mu.Unlock()\n\n\tdefer func() {\n\t\tp.mu.Lock()\n\t\tp.conn = nil\n\t\tp.mu.Unlock()\n\t\tconn.Close()\n\n\t\t// Drain pending ACK channels so waiting goroutines are unblocked\n\t\t// and stale entries do not accumulate across reconnections.\n\t\t// Collect keys first, then delete — Range+Delete in callback is\n\t\t// not guaranteed safe by the sync.Map contract.\n\t\tvar staleKeys []any\n\t\tp.pendingAcks.Range(func(key, value any) bool {","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/wecom/websocket.go#L175-L211","documentation":"runConnection dials the WeCom WebSocket endpoint with websocket.DefaultDialer.DialContext; this error wraps any dial failure. The connectLoop caller typically retries with backoff, so this error is an intermediate, retryable failure describing why the TCP/TLS/WebSocket handshake did not complete.","triggerScenarios":"DialContext fails due to DNS resolution failure, unreachable host, refused TCP connection, TLS handshake error, or context cancellation (p.ctx done) during the dial.","commonSituations":"Corporate firewall/proxy blocking wss:// traffic to the WeCom endpoint; DNS misconfiguration; machine offline or network flapping; p.ctx canceled during shutdown producing 'context canceled' wrapped here.","solutions":["Check basic connectivity to the WeCom websocket endpoint (DNS, firewall, proxy).","Inspect the wrapped cause: 'connection refused' vs 'no such host' vs 'context canceled' point to different fixes.","If it is 'context canceled', the platform was shutting down — no action needed; the connect loop should stop.","Add a proxy configuration if the host requires one to reach external wss:// endpoints.","Rely on connectLoop backoff for transient network blips; alert only if it never recovers."],"exampleFix":"null","handlingStrategy":"retry","validationCode":"conn, err := net.DialTimeout(\"tcp\", hostPort, 5*time.Second)\nif err != nil { return fmt.Errorf(\"endpoint unreachable: %w\", err) } // pre-check before starting the platform","typeGuard":"null","tryCatchPattern":"if err := platform.Start(ctx); err != nil {\n\tif errors.Is(err, context.Canceled) { return nil } // expected during shutdown\n\tbackoffRetry(err)\n}","preventionTips":["Pre-check DNS/firewall reachability of the wss endpoint","Configure proxy settings where required","Alert on connectLoop exhausting retries rather than single failures"],"tags":["wecom","websocket","network","dial"],"backgroundTag":"connection-refused","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}