镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

[Bug] Mobile: replies sent in a nested thread never appear — thread query is root-scoped #2415

Open

Description

@mdmohsin7

Summary

On mobile, replies sent inside a nested thread (a thread opened on a reply, rather than on a top-level channel message) never appear. The message is signed, published, accepted by the relay, and visible to other clients — but the sender's own screen stays empty, with no error and no way to recover. Leaving the channel, pull-to-refresh, and restarting the app all fail to surface it.

It reads as data loss from the user's side: you type a message, it disappears, and only by opening desktop do you discover it was delivered the whole time.

Reproduction

  1. On mobile, open a channel and post a message — call it R.
  2. Open R's thread and post a reply — call it M.
  3. From inside R's thread, open M's own thread (the nested-thread row).
  4. Send any message there.

Expected: the message appears in M's thread.
Actual: nothing appears. The message is on the relay and renders on desktop.

Not specific to @-mentions or agents — plain text reproduces it. Verified on 7e34bee6.

Root cause

The relay's thread query is root-scoped (buzz-db/src/thread.rs#L397-L398):

WHERE tm.community_id = $1
  AND tm.root_event_id = $2

It returns rows whose root is the supplied id, relying on depth (not parentage) to bound the result.

Mobile passes the nested thread's head as if it were a root (thread_detail_page.dart#L56-L58):

final repliesState = ref.watch(
  threadRepliesProvider(
    ThreadRepliesArgs(channelId: channelId, rootId: threadHead.id),
  ),
);

which becomes '#e': [args.rootId] in thread_replies_provider.dart#L56.

But a reply to M is stored with root_event_id = R, parent_event_id = M — the relay derives the root from the root marker and only falls back to the parent when absent (ingest.rs#L632):

let effective_root = meta.root_event_id.unwrap_or_else(|| parent_bytes.clone());

And mobile's own send path writes exactly that marker pair for a nested reply (send_message_provider.dart#L122-L136):

return [
  ['e', root, '', 'root'],
  ['e', parentEventId, '', 'reply'],
];

So root_event_id = M matches zero rows, and M's thread view is permanently empty. The write side is correct; only the read query is wrong.

Why desktop is unaffected

Desktop has no nested thread view. openThreadHeadId is only ever set from a top-level timeline message (ChannelScreen.tsx#L163-L166), so the id it queries with is always a genuine root and the root-scoped query returns every descendant at any depth. Mobile added nested-thread navigation (thread_detail_page.dart#L300) without adapting the query.

Possible fixes

Option A — query the true root, filter client-side (mobile only).
ThreadDetailPage already computes the right value one screen further down, for the compose bar (#L136):

final effectiveRootId = threadHead.rootId ?? threadHead.id;

Passing that to threadRepliesProvider is sufficient — the page already indexes replies by parent and selects childrenByParent[threadHead.id] (#L71-L78), so the narrowing is already implemented. Live refresh also already invalidates on both root and parent (channel_messages_provider.dart#L187-L208).

Small and matches desktop's effective behaviour. Cost: a nested view fetches the entire root thread and discards most of it, which grows with thread size.

Option B — support parent-scoped thread queries in the relay.
Add an opt-in filter so the query can bound on parent_event_id (or on a subtree) instead of root_event_id, and have mobile use it. No over-fetching and it makes nested threads a first-class concept, but it is a relay change with migration and API-surface implications.

Happy to send a PR for Option A, or for Option B if that is the preferred direction — I'd rather confirm before writing relay code.

Environment

  • main @ 7e34bee6
  • Buzz Mobile on a physical iPhone XR (not a simulator)
  • Reproduced against a relay where the same events render correctly on desktop

Activity

  1. skyerus commented on Jul 26, 2026

    @skyerus

    Bump. Also having this issue.

  2. zacklavin11 commented on Jul 26, 2026

    @zacklavin11

    Also hitting this on phone — nested-thread replies appear on desktop / on the relay, empty on mobile. Makes mobile almost unusable for real threaded work.

    Fix PR is open: #2477

    Status as of now:

    • fix is small and looks correct
    • blocked on merge conflicts against current main (mergeable: CONFLICTING)
    • no review yet

    Bumping for visibility — please rebase #2477 so it can land.

  3. assagman commented on Aug 1, 2026

    @assagman

    Up ⤴️

    This is a huge blocker for us to use mobile app.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions