Skip to content

Commit 53c9b2f

Browse files
committed
fix(stream-management): handle queue desync after page reload
When a page/app reloads, the outbound queue (outbound_q) is not persisted but the server maintains its acknowledgment counter. On session resume: 1. Server sends <resumed h="N"/> with the real counter value 2. Client tries to remove N items from an empty queue 3. shift() returns undefined, causing a crash on item.stanza This fix adds a guard that: - Detects when queue is empty but server reports higher h value - Resyncs the outbound counter to match server's value - Breaks out of the loop to prevent the crash Note: In-flight stanzas (sent but unacked at reload time) are still lost since the queue is not persisted. A proper fix would require serializing the queue to storage, which is beyond the scope of this patch.
1 parent d9facdc commit 53c9b2f

1 file changed

Lines changed: 14 additions & 0 deletions

File tree

packages/stream-management/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,20 @@ export default function streamManagement({
9191
const oldOutbound = sm.outbound;
9292
for (let i = 0; i < +n - oldOutbound; i++) {
9393
const item = sm.outbound_q.shift();
94+
if (!item) {
95+
// Queue is empty but server reports higher h value.
96+
// This can happen after page/app reload when the queue wasn't persisted:
97+
// - Client sends stanzas, server acks them (h increases)
98+
// - Page reloads: outbound_q is lost, outbound resets to 0
99+
// - On resume, server sends <resumed h="N"/> with the real counter
100+
// - We try to remove N items from an empty queue
101+
//
102+
// Resync outbound to server's value to prevent future desyncs.
103+
// Note: Any stanzas that were in-flight (sent but unacked) at reload
104+
// time are lost - the queue is not persisted across reloads.
105+
sm.outbound = +n;
106+
break;
107+
}
94108
sm.outbound++;
95109
sm.emit("ack", item.stanza);
96110
}

0 commit comments

Comments
 (0)