Skip to content

Stop an own chat send from staying on Sending until reload #306

Description

@HMarzban

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

  1. Sign in on the local stack. Open a pad, add a heading, open its chat.
  2. Send a message. Wait 10 seconds. It still shows the pending clock.
  3. Reload and open the same chat. The message is there as sent.

Acceptance criteria

Activity

  1. added
    bugSomething isn't working
    ChatRelated to chat features
    on Sep 21, 2026
  2. HMarzban commented on Sep 22, 2026

    @HMarzban
    CollaboratorAuthor

    Root cause, for the record. useChannelMessages set newestSeqRef to null for an empty first window. The realtime drain reads null as "window not loaded", so it never merged the first echo, and the row kept its clock until a reload. Fixed in 99e4593: an empty first window sets 0.

    The channel-reuse hypothesis in the issue body was not the cause. Checked in a signed-in browser: the first send in an empty chat, and the first send after joining, both turn sent in about 2 s.

  3. added a commit that references this issue on Sep 22, 2026
    99e4593
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ChatRelated to chat featuresbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions