Discord: When left unattended for extended periods of time the userlist begins duplicating users #230

Closed
opened 2026-09-13 12:50:33 -04:00 by Salastil · 1 comment
Owner

image.png

The userlist starts duplicating users, likely because we're just appending and not deduping users as status changes change from online to offline over time.

Expected behavior: Each user is unique and should only have one listing.

![image.png](/attachments/9a58a527-980e-403c-ae91-cd7d386e4512) The userlist starts duplicating users, likely because we're just appending and not deduping users as status changes change from online to offline over time. Expected behavior: Each user is unique and should only have one listing.
Salastil added the bug label 2026-09-13 12:50:40 -04:00
Author
Owner

Finished.

The cause was index alignment rather than appending. Discord's member list interleaves group headers - Online, Offline, and every role with its own section - among the people, and its incremental INSERT/UPDATE/DELETE ops address that list. We dropped the headers on SYNC, so every index we applied was short by the number of headers above it: the DELETE half of a status change removed whoever happened to sit at that position instead, and the INSERT half added a second copy of the person who had moved, whose old row was still there. One duplicate per status change, which is why it only shows after a channel has been left open a while.

Headers now take their slot in the window and are filtered out when the roster is emitted. An op that still does not fit means the window has drifted from Discord's, so it is discarded and a fresh SYNC requested rather than applied half-aligned. The roster also de-dupes by user id on the way out, so the symptom cannot return by another route.

nobilis 276bbb0, moho 80d53ed. Five tests cover it, including one that replays the exact DELETE/INSERT pair a status change sends across a section boundary.

Finished. The cause was index alignment rather than appending. Discord's member list interleaves group headers - Online, Offline, and every role with its own section - among the people, and its incremental INSERT/UPDATE/DELETE ops address *that* list. We dropped the headers on SYNC, so every index we applied was short by the number of headers above it: the DELETE half of a status change removed whoever happened to sit at that position instead, and the INSERT half added a second copy of the person who had moved, whose old row was still there. One duplicate per status change, which is why it only shows after a channel has been left open a while. Headers now take their slot in the window and are filtered out when the roster is emitted. An op that still does not fit means the window has drifted from Discord's, so it is discarded and a fresh SYNC requested rather than applied half-aligned. The roster also de-dupes by user id on the way out, so the symptom cannot return by another route. nobilis [276bbb0](https://git.salastil.com/Salastil/nobilis/commit/276bbb0), moho [80d53ed](https://git.salastil.com/Salastil/moho/commit/80d53ed). Five tests cover it, including one that replays the exact DELETE/INSERT pair a status change sends across a section boundary.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Salastil/moho#230