AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

Dev HMR Client Reconnects Forever After Prerender Activation (Visibilitychange While Socket Is CONNECTING)

In Next.js dev, when a prerendered page is activated while the HMR WebSocket is still in CONNECTING state, the client enters an infinite reconnect loop. This prevents page hydration and floods the server with repeated /_next/hmr upgrade requests.

highConfidence 95%Next.jsAffected V16.3.3Affected V16.4.0-Canary.15

Origin Analysis

The visibilitychange handler in web-socket.ts calls init() whenever readyState is not OPEN, including CONNECTING. init() closes the existing socket without clearing its onclose/onerror callbacks. The closed socket's onclose then schedules another init() after 1 second, creating an endless cycle because reconnections reset on every onopen.
1. Clone https://github.com/hairywelly/next-hmr-visibility-repro 2. npm install && npm run dev 3. In Chrome open http://localhost:3000 (with Speculation Rules prerender enabled) 4. Wait a second, click the link to /target (or open /?auto) 5. Open console on /target; observe repeated WebSocket errors and [HMR] connected messages

Fixing Code Block

Edge Case Audit

This change assumes that a socket in CLOSING state does not need reconnection upon visibility change. In rare cases where the socket is stuck in CLOSING, the page may not reconnect until another event. Test with multiple tabs and rapid visibility toggling. If the issue persists, revert to the original code and wait for an official fix, as this patch only addresses the symptom of the infinite loop, not the underlying race between visibilitychange and socket lifecycle. Consider adding a guard against reentrant init() calls for extra safety.

Ecosystem Topology