{"record":{"id":"98ef3d710a58b75b","repo":"sipeed/picoclaw","slug":"connect-w","errorCode":null,"errorMessage":"connect: %w","messagePattern":"connect: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/channels/whatsapp_native/whatsapp_native.go","lineNumber":165,"sourceCode":"\t\tif startOK {\n\t\t\treturn\n\t\t}\n\t\tc.runCancel()\n\t\tclient.Disconnect()\n\t\tc.mu.Lock()\n\t\tc.client = nil\n\t\tc.container = nil\n\t\tc.mu.Unlock()\n\t\t_ = container.Close()\n\t}()\n\n\tif client.Store.ID == nil {\n\t\tqrChan, err := client.GetQRChannel(c.runCtx)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"get QR channel: %w\", err)\n\t\t}\n\t\tif err := client.Connect(); err != nil {\n\t\t\treturn fmt.Errorf(\"connect: %w\", err)\n\t\t}\n\t\t// Handle QR events in a background goroutine so Start() returns\n\t\t// promptly.  The goroutine is tracked via c.wg and respects\n\t\t// c.runCtx for cancellation.\n\t\t// Guard wg.Add with reconnectMu + stopping check (same protocol\n\t\t// as eventHandler) so a concurrent Stop() cannot enter wg.Wait()\n\t\t// while we call wg.Add(1).\n\t\tc.reconnectMu.Lock()\n\t\tif c.stopping.Load() {\n\t\t\tc.reconnectMu.Unlock()\n\t\t\treturn fmt.Errorf(\"channel stopped during QR setup\")\n\t\t}\n\t\tc.wg.Add(1)\n\t\tc.reconnectMu.Unlock()\n\t\tgo func() {\n\t\t\tdefer c.wg.Done()\n\t\t\tfor {\n\t\t\t\tselect {","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/channels/whatsapp_native/whatsapp_native.go#L147-L183","documentation":"Returned by WhatsAppNativeChannel.Start when client.Connect() fails right after successfully acquiring the QR channel for an unpaired device. whatsmeow's Connect opens its websocket to WhatsApp servers; failure means the socket could not be established at all (DNS, TLS, firewall, proxy) - QR events would never arrive otherwise. The deferred cleanup runs, closing everything.","triggerScenarios":"Unpaired device + GetQRChannel ok, then whatsapp web websocket (wss to web.whatsapp.com) dial fails: no internet egress, WhatsApp endpoints blocked by firewall/GFW, corporate proxy required but unset, or outdated whatsmeow failing the websocket handshake after a WA protocol change.","commonSituations":"Hosts in regions where WhatsApp is blocked without a VPN/proxy; datacenter egress filtering; whatsmeow library too old for current WhatsApp server behavior (fixed by library updates); DNS resolution failures for *.whatsapp.com.","solutions":["Verify the host can reach wss://web.whatsapp.com (curl/openssl probe) and that DNS resolves.","If a proxy is required, configure HTTPS_PROXY/WSS proxy support for the process.","Update picoclaw to a build with a current whatsmeow version when WhatsApp protocol changes break connects.","Retry Start after transient network outages; this is a startup-time hard failure."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if _, err := net.LookupHost(\"web.whatsapp.com\"); err != nil {\n    return fmt.Errorf(\"cannot resolve WhatsApp endpoints: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := ch.Start(ctx); err != nil {\n    if strings.Contains(err.Error(), \"connect:\") {\n        // network-level failure; check egress/proxy, then retry Start with backoff\n    }\n}","preventionTips":["Ensure egress to web.whatsapp.com:443 is allowed before deploying.","Configure proxy env vars in restricted networks.","Keep whatsmeow updated via picoclaw releases."],"tags":["whatsapp","whatsmeow","connect","network","firewall","qr-login"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}