[Bug]: Pairing-code retry exhaustion and page errors answer 500 instead of 503
POST /api/sessions/{sessionId}/pairing-code on the whatsapp-web.js engine answers HTTP 500 when its retry budget is exhausted, and when the in-page call throws. Both are conditions a caller can retry, and the repository already has the error class that says so.
Steps to reproduce
- Start a whatsapp-web.js session and wait for
qr_ready. POST /api/sessions/{sessionId}/pairing-codewhile WhatsApp Web is cycling its QR page.- Observe the response when every attempt lands mid-navigation, and when WhatsApp Web raises an error inside the evaluated function.
Expected
A 503 for an exhausted transport retry budget, which is the contract EngineTransportError already carries, and a documented status for an engine-side rejection. A 500 tells a client the gateway is broken and that retrying is pointless.
Actual
Both paths answer 500 with a raw message. The observed shapes are requestPairingCode attempt timed out and a minified WhatsApp Web exception whose message is literally t: t. docs/06-api-specification.md:801 documents 400, 401, 403, 404 and 409 for this route and no 5xx at all, so neither response matches the published contract.
Root cause
src/engine/adapters/wwebjs-lifecycle.ts:60-66definesPairingCodeAttemptTimeoutError extends Error, a plainError.src/engine/adapters/wwebjs-lifecycle.ts:1077-1078ends the retry loop withthrow lastError, so that plainErrorreaches the client.src/engine/adapters/wwebjs-lifecycle.ts:1058-1060rethrows any non-navigation error raw on the first attempt.- No global exception filter or interceptor is registered, so Nest's built-in handler turns any non-
HttpExceptioninto a500. Every other engine error maps by subclassing:EngineNotReadyErrorto409(src/common/errors/engine-not-ready.error.ts:13),EngineNotSupportedErrorto501(src/common/errors/engine-not-supported.error.ts:12),EngineTransportErrorto503(src/common/errors/engine-transport.error.ts:14). src/engine/adapters/wwebjs-pairing-code.spec.ts:55-70pins the plainErroras the expected outcome, so the gap is currently locked in by a test.
The retry loop itself came from #1543, whose suggested fix ended the loop with EngineTransportError; the shipped code ends it with throw lastError.
Suggested direction
End the retry loop with EngineTransportError, keeping the last error's message as the detail so the diagnostic is not lost. Decide separately whether a non-navigation engine rejection should keep propagating raw or be wrapped; if it keeps propagating, document the status the route answers for it. Update the spec and the route's documented error list, which means a new @ApiResponse and a regenerated OpenAPI snapshot.
Environment
- OpenWA 0.23.4 and a build of
mainat 62dbe393 - Engine: whatsapp-web.js 1.34.7
Source: rmyndharis/OpenWA