Is there an existing issue for this?
Is this a problem caused by your code, or is it specifically because of the library?
Describe the bug.
After a user successfully scans a QR code and WhatsApp Web begins loading (reaching 95-99% progress), the client unexpectedly disconnects with Max qrcode retries reached after about 2-3 minutes.
Two related problems in the QR handling code in Client.js:
1. change:ref listener is never cleaned up
The listener registered on AuthStore.Conn (line ~191) is never removed after a successful QR scan. When WhatsApp Web clears the ref property during/after authentication (setting it to null or undefined), the listener fires onQRChangedEvent with an invalid ref value, which:
- Emits a malformed QR event (the QR string starts with
"undefined," instead of "2@...")
- Increments
qrRetries past qrMaxRetries
- Triggers a
DISCONNECTED event with reason "Max qrcode retries reached"
- Calls
destroy(), killing the session even though authentication was in progress
2. qrRetries is never reset after a successful scan
The qrRetries counter only goes up. If the user waits through several QR refreshes before scanning, the counter is already close to the limit. Even if the null ref is guarded against, any legitimate post-scan QR event (e.g. if linking fails and WA Web falls back to QR) would immediately hit the retry limit, giving the user zero chance to try again.
Evidence from logs
The bug is clearly visible in the QR data:
- Normal QR codes (before scan):
qrLength=239, ref starts with 2@...
- Spurious QR after scan:
qrLength=146, ref is literally "undefined"
The math confirms it: 239 - 102 (normal ref length) + 9 ("undefined" length) = 146. The change:ref callback received undefined as the ref value.
Timeline from production logs:
08:15:29 QR #1 (initial) qrRetries=1
08:16:29 QR #2 (change:ref, normal rotate) qrRetries=2
08:16:49 QR #3 (change:ref) qrRetries=3
08:17:09 QR #4 (change:ref) qrRetries=4 (= qrMaxRetries, no disconnect)
08:17:17 USER SCANS QR - loading 95% then 99%
08:20:14 QR #5 (change:ref, ref=undefined) qrRetries=5 > 4 -> DISCONNECT!
Expected behavior
After a successful QR scan:
- The
change:ref listener should stop emitting QR events
- The
qrRetries counter should reset, so that if linking fails and WA Web falls back to QR, the user gets a fresh set of retry attempts
Steps to Reproduce the Bug or Issue
- Create a client with
qrMaxRetries set to a low value (e.g., 4)
- Let 3-4 QR refresh cycles pass before scanning
- Scan the QR code - observe loading screen reaching 95-99%
- Wait 2-3 minutes for WhatsApp Web to clear/reset the ref
- Client disconnects with "Max qrcode retries reached" despite successful scan
The issue is timing-dependent: it requires enough QR refreshes before scan so that qrRetries is close to qrMaxRetries, and then a post-scan change:ref event pushes it over the limit.
Relevant Code
In src/Client.js, the change:ref listener (line ~191) is registered as an anonymous function with no cleanup:
window.AuthStore.Conn.on('change:ref', (_, ref) => {
window.onQRChangedEvent(getQR(ref));
});
Three problems:
- No null guard:
getQR(undefined) produces "undefined,..." instead of being silently ignored
- Never removed: The listener stays active after authentication, so any
ref change (including cleanup to null/undefined) triggers a QR event and increments the retry counter
- Counter never resets:
qrRetries only increments, so pre-scan QR refreshes eat into the post-scan budget
Proposed fix
- Reset
qrRetries when loading_screen fires (the QR was successfully scanned)
- Guard against null/undefined
ref in the change:ref callback
- Remove the
change:ref listener when change:hasSynced fires (authentication complete)
PR: #127090
Browser Type
Chromium
WhatsApp Account Type
Standard
WhatsApp Web Version
2.3000+
Is there an existing issue for this?
Is this a problem caused by your code, or is it specifically because of the library?
Describe the bug.
After a user successfully scans a QR code and WhatsApp Web begins loading (reaching 95-99% progress), the client unexpectedly disconnects with
Max qrcode retries reachedafter about 2-3 minutes.Two related problems in the QR handling code in
Client.js:1.
change:reflistener is never cleaned upThe listener registered on
AuthStore.Conn(line ~191) is never removed after a successful QR scan. When WhatsApp Web clears therefproperty during/after authentication (setting it tonullorundefined), the listener firesonQRChangedEventwith an invalid ref value, which:"undefined,"instead of"2@...")qrRetriespastqrMaxRetriesDISCONNECTEDevent with reason"Max qrcode retries reached"destroy(), killing the session even though authentication was in progress2.
qrRetriesis never reset after a successful scanThe
qrRetriescounter only goes up. If the user waits through several QR refreshes before scanning, the counter is already close to the limit. Even if the null ref is guarded against, any legitimate post-scan QR event (e.g. if linking fails and WA Web falls back to QR) would immediately hit the retry limit, giving the user zero chance to try again.Evidence from logs
The bug is clearly visible in the QR data:
qrLength=239, ref starts with2@...qrLength=146, ref is literally"undefined"The math confirms it:
239 - 102 (normal ref length) + 9 ("undefined" length) = 146. Thechange:refcallback receivedundefinedas the ref value.Timeline from production logs:
Expected behavior
After a successful QR scan:
change:reflistener should stop emitting QR eventsqrRetriescounter should reset, so that if linking fails and WA Web falls back to QR, the user gets a fresh set of retry attemptsSteps to Reproduce the Bug or Issue
qrMaxRetriesset to a low value (e.g., 4)The issue is timing-dependent: it requires enough QR refreshes before scan so that
qrRetriesis close toqrMaxRetries, and then a post-scanchange:refevent pushes it over the limit.Relevant Code
In
src/Client.js, thechange:reflistener (line ~191) is registered as an anonymous function with no cleanup:Three problems:
getQR(undefined)produces"undefined,..."instead of being silently ignoredrefchange (including cleanup to null/undefined) triggers a QR event and increments the retry counterqrRetriesonly increments, so pre-scan QR refreshes eat into the post-scan budgetProposed fix
qrRetrieswhenloading_screenfires (the QR was successfully scanned)refin thechange:refcallbackchange:reflistener whenchange:hasSyncedfires (authentication complete)PR: #127090
Browser Type
Chromium
WhatsApp Account Type
Standard
WhatsApp Web Version
2.3000+