{"record":{"id":"2504291cf31847fe","repo":"sipeed/picoclaw","slug":"whatsapp-not-yet-paired-qr-login-pending-w","errorCode":null,"errorMessage":"whatsapp not yet paired (QR login pending): %w","messagePattern":"whatsapp not yet paired \\(QR login pending\\): %w","errorType":"exception","errorClass":"channels.ErrTemporary","httpStatus":null,"severity":"error","filePath":"pkg/channels/whatsapp_native/whatsapp_native.go","lineNumber":431,"sourceCode":"\t}\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\tdefault:\n\t}\n\n\tc.mu.Lock()\n\tclient := c.client\n\tc.mu.Unlock()\n\n\tif client == nil || !client.IsConnected() {\n\t\treturn nil, fmt.Errorf(\"whatsapp connection not established: %w\", channels.ErrTemporary)\n\t}\n\n\t// Detect unpaired state: the client is connected (to WhatsApp servers)\n\t// but has not completed QR-login yet, so sending would fail.\n\tif client.Store.ID == nil {\n\t\treturn nil, fmt.Errorf(\"whatsapp not yet paired (QR login pending): %w\", channels.ErrTemporary)\n\t}\n\n\tto, err := parseJID(msg.ChatID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid chat id %q: %w\", msg.ChatID, err)\n\t}\n\n\twaMsg := &waE2E.Message{\n\t\tConversation: proto.String(msg.Content),\n\t}\n\n\tif _, err = client.SendMessage(ctx, to, waMsg); err != nil {\n\t\treturn nil, fmt.Errorf(\"whatsapp send: %w\", channels.ErrTemporary)\n\t}\n\treturn nil, nil\n}\n\n// parseJID converts a chat ID (phone number or JID string) to types.JID.","sourceCodeStart":413,"sourceCodeEnd":449,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/channels/whatsapp_native/whatsapp_native.go#L413-L449","documentation":"Returned by WhatsAppNativeChannel.Send when the whatsmeow client IS connected to WhatsApp servers but client.Store.ID is nil - the device has not completed QR pairing, so it has no WhatsApp identity and cannot send messages. Wraps channels.ErrTemporary, so the manager keeps retrying with backoff, but retries cannot succeed until a human scans the QR code.","triggerScenarios":"Fresh install (new store) where Start() launched the QR flow but nobody has scanned it yet; a re-pair after store deletion; scans pending while outbound traffic is already routed to the channel.","commonSituations":"Operator deploys the native WhatsApp channel and sends a test message before completing the console QR login; the QR code expired (whatsmeow refreshes it, but pairing still pending); tests in CI without any paired device.","solutions":["Watch the process stdout/console for the rendered QR (qrterminal) and scan it from the WhatsApp phone app: Linked devices > Link a device.","Keep the process running - pairing only progresses while the channel is up.","After the 'success' QR event, retry sending (manager backoff will, or trigger manually).","If the QR keeps expiring unscanned, reduce the delay between Start and scanning."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Do not route outbound traffic until the device is paired.\n// If the channel exposes pairing state (client.Store.ID != nil), gate sends on it;\n// otherwise delay sends until the 'success' QR event appears in logs.","typeGuard":"func isTemporary(err error) bool { return errors.Is(err, channels.ErrTemporary) }","tryCatchPattern":"if _, err := ch.Send(ctx, msg); err != nil {\n    if strings.Contains(err.Error(), \"not yet paired\") {\n        // surface to operator: scan the QR code; retry send after login succeeds\n    }\n}","preventionTips":["Complete QR pairing immediately after first Start and before enabling outbound routing.","Alert on this specific message - retrying without pairing never succeeds.","Keep the channel running during pairing; QR refresh requires an active client."],"tags":["whatsapp","qr-login","pairing","not-paired"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}