Problem
For a signed-in member, a message they send can stay in the pending state ("Sending") and never turn into sent. A
new comment can also fail to appear in the feed. A reload shows both, so the data is saved. The bug is older than
the 2026-09-21 composer round: a git archive HEAD copy of 7ed771158 does the same.
What was measured (local stack, 2026-09-21)
- The inserts succeed:
POST /rest/v1/messages returns 201, and the rows are in public.messages.
- Realtime delivers them. A supabase-js probe subscribed to
chatroom:<channelId> got each INSERT at once,
both as anon and as the same signed-in user (row-level security as authenticated). The
realtime.subscription rows exist, and both replication slots are caught up.
- So the server side works, and the feed does not merge the echo.
- In the page, the feed showed "No messages yet!" while it held one pending row. The "New messages" divider sat
in the middle of the list. One send reached the database and was then missing from the list.
Lead
useChannelRealtime merges an arrival into the list only when dataIncludesTailRef.current is true.
Otherwise the arrival goes to detachedBufferRef and counts as "new", so an own optimistic row never turns
sent. The observations fit a loaded window that does not include the tail, or a window that lands after the send
and replaces the list (see the chatroom CLAUDE.md bullet "A purge replace lands late"). Next step: read
dataIncludesTailRef and newestSeqRef at the moment a send stays pending.
A second, unproven hypothesis: realtime-js 2.116 channel(topic) returns a still-listed channel with the same
topic, and removeChannel completes asynchronously. So a fast unsubscribe and resubscribe on one topic can reuse
a closing channel (React Strict Mode does this on mount in development). A fix for this alone did not change the
symptom, so it is not the cause shown here.
Steps to reproduce
- Sign in on the local stack. Open a pad, add a heading, open its chat.
- Send a message. Wait 10 seconds. It still shows the pending clock.
- Reload and open the same chat. The message is there as sent.
Acceptance criteria
Problem
For a signed-in member, a message they send can stay in the pending state ("Sending") and never turn into sent. A
new comment can also fail to appear in the feed. A reload shows both, so the data is saved. The bug is older than
the 2026-09-21 composer round: a
git archive HEADcopy of7ed771158does the same.What was measured (local stack, 2026-09-21)
POST /rest/v1/messagesreturns 201, and the rows are inpublic.messages.chatroom:<channelId>got eachINSERTat once,both as anon and as the same signed-in user (row-level security as
authenticated). Therealtime.subscriptionrows exist, and both replication slots are caught up.in the middle of the list. One send reached the database and was then missing from the list.
Lead
useChannelRealtimemerges an arrival into the list only whendataIncludesTailRef.currentis true.Otherwise the arrival goes to
detachedBufferRefand counts as "new", so an own optimistic row never turnssent. The observations fit a loaded window that does not include the tail, or a window that lands after the send
and replaces the list (see the chatroom
CLAUDE.mdbullet "A purge replace lands late"). Next step: readdataIncludesTailRefandnewestSeqRefat the moment a send stays pending.A second, unproven hypothesis: realtime-js 2.116
channel(topic)returns a still-listed channel with the sametopic, and
removeChannelcompletes asynchronously. So a fast unsubscribe and resubscribe on one topic can reusea closing channel (React Strict Mode does this on mount in development). A fix for this alone did not change the
symptom, so it is not the cause shown here.
Steps to reproduce
Acceptance criteria