Added
- A previously linked session that comes back asking for a QR now logs a warning (
relink_required) naming the
likely causes, since an unlink that happened while the engine was down can leave no other trace.
Changed
GET /searchdeclares the plugin provider's failure answers in the contract:502for an invalid result
shape and503when the provider does not answer; the built-in provider never returns either.POST /sessions/{sessionId}/pairing-code: the 409 description in the OpenAPI contract and API reference
now says to wait forqr_ready, notready, which on this route means the session is already linked, and
to wait forreadyonce a code was accepted.GET /sessions/{sessionId}/qrno longer declares the engine-not-ready 409: the route reads the engine's
cached QR and never answers one. Its 400 already covers the not-ready case.
Fixed
- Session auto-start no longer runs twice at boot. The plugin port for
SessionServicewas a factory returning
the same instance, which made Nest dispatch its lifecycle hooks twice: two auto-start loops raced, each
session loggedAuto-start failedwithSession is already starting, and the 2 s launch stagger was lost. - Baileys: requesting a pairing code before the session reaches
qr_readyanswers the documented 409 instead
of a 500 with aConnection Closedstack trace, the same guard the whatsapp-web.js engine already carried.
Thanks @m7fz7. - Baileys: once WhatsApp accepts a QR scan or pairing code the session leaves
qr_ready(authenticating,
theninitializingacross the restart WhatsApp requests) and ignores the QR refreshes Baileys keeps
emitting until then, so a repeat pairing request answers 409 instead of overwriting the linked identity. - Baileys: a QR that finishes rendering after its socket dropped is discarded instead of marking the session
qr_ready. - A WhatsApp-initiated unlink now clears the session's
phonethe way an operator logout does, so a restart
no longer relaunches the unlinked session into a QR nobody asked for; the next successful link sets it
again. - Baileys: a pairing request on a socket that has already begun closing answers the documented 409 instead of
a 500, and no longer writes a half-registered identity into the session's stored credentials. - Both engines drop the cached QR as soon as its socket or page dies, so
GET /sessions/{sessionId}/qr
answers its documented 400 instead of 200 with a code that can no longer be scanned.
Documentation
- The upgrade runbook and the migration guide state the
docker-compose.dev.ymlcaveat before the first
docker composecommand instead of after it, and name theopenwaservice substitution it needs. GET /api/healthis documented consistently as withholdingversionfrom unauthenticated callers.
Dependencies
@bull-board/{api,express,nestjs}8.6.1 to 9.3.2 (major), plus a minor/patch group (NestJS 11.2.1,
BullMQ 6.2.0, AWS SDK) and a dashboard group (Vite 8.2.2, i18next 26.4.0, lucide-react 1.33).
Upgrade notes (behavior changes)
- The queue dashboard's obliterate action gained a force option in Bull Board 9. Forcing it deletes
active jobs as well as queued ones, so those deliveries never reach a final attempt and no
webhook_delivery_failuresrow is written for them. Bull Board 8 refused outright while jobs were
active. The route stays ADMIN-only behindBullBoardAuthMiddleware.