sendMessage with image can hit Connection Closed while socket is still connecting
Bug description
Sending an image right after the socket connects sometimes throws Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed }) from sendRawMessage in Socket/socket.ts, even though the app never sees a close event and the reconnect never fires. Sending text at the same moment works fine.
Root cause I found
sendMessage with an image goes through waUploadToServer, which calls refreshMediaConn(false). That calls query() on the socket to fetch an upload URL. query() calls sendNode() -> sendRawMessage(), which guards with if (!ws.isOpen) throw ....
I patched sendRawMessage locally to log the socket state right before that throw and caught this:
ws.isOpen=false ws.isClosed=false ws.isClosing=false ws.isConnecting=true
ws.socket=present readyState=0readyState=0 is WebSocket.CONNECTING. The underlying WebSocket handshake had not finished yet when refreshMediaConn tried to use it.
Text messages almost never hit this because they only need one round trip (sendNode). Image messages need at least two sequential round trips (the media conn query, then the actual upload), so the window where the socket might still be connecting is much wider.
Fix
waitForSocketOpen() already exists on the returned socket and does exactly the right thing (resolves once open, throws if closed/closing, waits if still connecting). Calling it before sendMessage closes the race:
await sock.waitForSocketOpen();
await sock.sendMessage(jid, { image, caption });Tested this against a real WhatsApp connection, both right after connecting and on an already-warm connection. Delivery succeeded every time after adding the wait; without it, it failed consistently on a fresh connection.
Suggestion
Maybe sendMessage (or at least the media upload path) should call waitForSocketOpen() internally before starting, so callers don't have to know about this themselves.
Versions
- @whiskeysockets/baileys: 6.7.24
- Node: 22.23.2
Source: WhiskeySockets/Baileys