Skip to content

fix: user search returns zero results for partially typed names#1603

Merged
tlongwell-block merged 1 commit into
mainfrom
eva/user-search-prefix-mode
Jul 8, 2026
Merged

fix: user search returns zero results for partially typed names#1603
tlongwell-block merged 1 commit into
mainfrom
eva/user-search-prefix-mode

Conversation

@tlongwell-block

Copy link
Copy Markdown
Collaborator

Problem

Wes reported a user missing from the add-member picker, and separately from the @mention popup (buzz-bugs thread). It looked like a result-count limit — it isn't. Every hop was traced: GUI asks for 25–50, the Tauri command clamps at 500, the relay bridge and FTS layer clamp at 500. Nothing truncates below what the UI displays.

The real bug: the search_users Tauri command — the single backend for all user typeahead surfaces (member picker, @mention popup, DM recipient search, topbar people results) — sends a plain NIP-50 search. The relay bridge runs that through websearch_to_tsquery whole-word matching, so a partially typed name matches nothing:

Live repro against staging (sprout-oss.stage):

query before after (search_mode: prefix)
tyl 0 1 (Tyler)
bax 0 3 (baxen, baxendev, …)
We 0 10+

Zero results reads as "user doesn't exist" — exactly what Wes saw mid-typing.

Fix

Opt user search into the relay's existing bridge-only search_mode: "prefix" extension — the same one the topbar message search already uses (build_search_messages_filter, messages.rs:134). Prefix mode keeps completed tokens exact and prefix-matches only the trailing token, server-side in Postgres, with all access checks unchanged.

Filter construction is extracted into build_user_search_filter and pinned by a unit test, mirroring the messages.rs convention, so the mode can't silently drift.

Not fixed here (by design)

The specific "Brad" case has a second, non-code cause: his kind:0 display_name is baxen — no profile on the relay contains "Brad" in its name (verified by paging all 3,443 kind:0 events). No search mode can fix that; it's a profile-naming question.

Testing

  • just desktop-tauri-test: 1006 passed, 0 failed (includes new user_search_filter_requests_prefix_mode_for_typeahead)
  • Live staging repro above via POST /query with and without search_mode

Every caller of the search_users Tauri command is a typeahead surface —
member picker, @mention popup, DM recipient search, topbar people
results. But the command sent a plain NIP-50 search, which the relay
bridge runs through websearch_to_tsquery whole-word matching: "tyl"
returned zero results for "Tyler", reading as "user doesn't exist" in
the picker.

Opt into the relay's existing bridge-only prefix search_mode (the same
extension the topbar message search already uses), extract the filter
into build_user_search_filter, and pin the mode with a unit test so it
can't drift.

Reproduced live against staging: "bax" 0 -> 3 results, "tyl" 0 -> 1.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve. Traced the claims against the code rather than re-running CI (all required checks are green, including the new unit test in Desktop Core).

Root cause verified: the relay bridge defaults NIP-50 search to whole-word FTS — extract_search_mode (crates/buzz-relay/src/api/bridge.rs:221) returns SearchMode::FullText unless the filter carries search_mode: "prefix", and search_users never sent it. SearchMode::Prefix (crates/buzz-search/src/query.rs:147) prefix-matches only the trailing token, and topbar message search already opts in the same way (messages.rs:113). Reproduced the symptom live through the current path: name lookup for tyl → 0 results, Tyler → 1.

Fix verified: one filter change through the single search_users backend that feeds every typeahead surface (member picker, @mention popup, DM recipient dialog, topbar people). Downstream client re-rank (rank_user_search_results) scores DISPLAY_PREFIX for partial-name hits, so prefix results survive the local filter instead of being dropped again. Extracted builder + pinned test mirrors the messages.rs convention. Minimal, correct, well-scoped.

Two non-blocking observations, both pre-existing and out of scope:

  • page in the filter is ignored server-side — handle_bridge_search hardcodes page: 1 ("no pagination for bridge MVP"), so the next_cursor the command emits pages nothing. Unchanged by this PR.
  • ForumComposer calls useMentions without channelType, so its mention popup never does a global user search at all — this fix reaches it only via the chat MessageComposer (which passes channelType for stream/forum/dm). Worth a follow-up if forum-post mentions should also find non-members.

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Thank you!

@tlongwell-block tlongwell-block merged commit 11608ef into main Jul 8, 2026
25 checks passed
@tlongwell-block tlongwell-block deleted the eva/user-search-prefix-mode branch July 8, 2026 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants