Connection State Recovery fails if client reconnects before server emits any events ("Zero-Event" reconnect)
I maintainer di solito rispondono entro 2 giorni
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 56/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- javascript, node.js, typescript
- Ambito
- backend-api-design, networking
Direzione di ricerca
Inizia dal gate di ripristino in socket.io/lib/namespace.ts e segui il modo in cui socket.io-client mantiene _lastOffset e invia l’handshake di riconnessione. Confronta il percorso senza eventi con restoreSession() e con il comportamento esistente di ripristino dello stato della connessione. Il lavoro è completato quando una riconnessione senza eventi precedenti conserva l’ID della sessione, le stanze e i dati, e segnala socket.recovered come true.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Describe the bug
When connectionStateRecovery is enabled, a client that connects, joins rooms, and disconnects before the server emits any events cannot recover its session on reconnection.
Even if the client reconnects within maxDisconnectionDuration, socket.recovered evaluates to false, a new socket.id is generated, and room memberships / socket.data are lost. This happens because _lastOffset on the client is undefined in the zero event case, causing the server's typeof offset === "string" check in namespace.ts to fail and bypass restoreSession().
To Reproduce
Socket.IO server version: 4.8.1
Server
import { Server } from "socket.io";
const io = new Server(3000, {
connectionStateRecovery: {
maxDisconnectionDuration: 2 * 60 * 1000,
},
});
io.on("connection", async (socket) => {
if (socket.recovered) {
console.log(`RECOVERED: ${socket.id} (rooms: ${Array.from(socket.rooms).join(", ")})`);
return;
}
console.log(`INITIAL CONNECT: ${socket.id}`);
await socket.join("room:alerts");
// Deliberately no events emitted to the client
});
Socket.IO client version: 4.8.1
Client
import { io } from "socket.io-client";
const socket = io("http://localhost:3000", {
reconnection: true,
});
socket.on("connect", () => {
console.log(`connect ${socket.id} (recovered: ${socket.recovered})`);
// Simulate a brief network drop shortly after connecting
setTimeout(() => {
socket.io.engine.close();
}, 200);
});
Expected behavior
When the client reconnects after the transient drop, the server should recognize the pid, restore the previous session (socket.id, room memberships, socket.data), and set socket.recovered = true.
Platform:
- Device: PC / Mac / Server
- OS: Linux / macOS / Windows
- Node.js version:
20.x/22.x
Additional context
-
Root Cause: In
socket.io-client,_lastOffsetremainsundefineduntil a packet of typeEVENTwith an offset is received. On reconnect, the handshake sends{ pid: "<id>", offset: undefined }. Insocket.io/lib/namespace.ts, recovery is gated by:if ( this.server.opts.connectionStateRecovery && typeof sessionId === "string" && typeof offset === "string" ) { session = await this.adapter.restoreSession(sessionId, offset); }Because
offsetisundefined,restoreSession()is skipped entirely despite having a valid activepid. -
Impact: Quiet subscriber channels (e.g. alert rooms, idle game lobbies) lose session state on brief network blips unless application code manually emits a synthetic dummy event on first connect to "prime"
_lastOffset. -
Potential Solutions:
- Include the current server stream offset in the initial
CONNECT(packet type0) handshake payload alongside{ sid, pid }so_lastOffsetis initialized at connection time. - Allow
restoreSession(sessionId, offset)to run whenoffsetisundefined, restoringid,rooms, anddatawithout replaying events.
- Include the current server stream offset in the initial
- Lingua principale
- TypeScript
- Stelle
- 63.2k
- Fork
- 10.3k
- Merge medio
- 3h 24m
- PR unite (30g)
- 1
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di socketio/socket.io
-
Raise Engine.IO minimum to 6.6.10 for published security fixesForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 1/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 2 giorni
-
Can't set response headers in Server.handleUpgradeForse già presa @MsfPablo l’ha presa 61 giorni fa. Apertaquestion
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
socketio/socket.io#5497 · 2 commenti ·
I maintainer di solito rispondono entro 2 giorni
-
WebTransport ignores query parameters in URLForse già presa @cyphercodes l’ha presa 149 giorni fa. Apertaneeds major release question
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
socketio/socket.io#5496 · 3 commenti ·
I maintainer di solito rispondono entro 2 giorni
-
"Basic CRUD application" can't be started with Angular clientForse già presa @lazerg l’ha presa 8 giorni fa. Apertato triage
Difficoltà 3/5 1-2 giorni Idoneità per principianti 65/100
I maintainer di solito rispondono entro 2 giorni
-
enhancement
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
socketio/socket.io#5512 · 6 commenti · 4 reazioni ·
I maintainer di solito rispondono entro 2 giorni
Tutte le issue di socketio/socket.io
Issue simili
-
A hung CI job runs for 6 hours before it is cancelledForse già presa @Olanetsoft l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
Olanetsoft/agent-lookout#110 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
thedotmack/claude-mem#4757 ·
I maintainer di solito rispondono entro 1 giorno
-
🐛 bug 🗺️ MCP OAuth
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
LibreChat-AI/LibreChat#17077 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 75/100