Stop a page-2 request from cancelling the folder you just opened

Fixkamo-internal
Shipped
August 15, 2026 at 1:47 AM UTC
Author
kamo
Commit
0f666d2

Junk, Trash, Archive and every custom folder showed the same mail — whatever was on screen before them. The server was not the problem: replaying listMessages against production Dovecot returns the right mail for each of those folders, and the metadata index is folder-scoped in both its query and its checkpoint. The list did it to itself. Switching folders resets the pagination state — page 0, hasMore back to true — before the new folder's first page has arrived, while the list is still rendering the folder just left. A short list has its last row inside the virtualizer's load-more threshold by definition, so the instant hasMore flipped back the list asked for page 2 of the new folder. That append then claimed a fresh sequence number, which cancelled both page-0 loads it had raced, and merged its own (empty) result into prev — the previous folder's rows. Nothing ever replaced them, so the folder after that inherited the same list, and so did the one after that. INBOX hid it twice over: it is where every visit starts, so there are no stale rows to keep, and with fifty rows loaded the last one is nowhere near the threshold unless you have scrolled. The first folder clicked was therefore right and every folder after it was wrong, which is exactly the shape of the report. Two rules now, extracted so they are the same rules the test asserts: an append never claims a new sequence number, because it cannot be the latest word on a list it is only extending; and no append goes out while the rows on screen belong to a folder other than the selected one. The finally block also clears only the flag its own load raised, so an append landing first no longer stops the spinner on a replace still in flight.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing