Skip to content

fix(reactions): accept emoji with variation selectors / ZWJ / skin tones (❤️ silently failed)#744

Merged
lilyshen0722 merged 2 commits into
mainfrom
fix/reaction-emoji-variation-selector
Jul 24, 2026
Merged

fix(reactions): accept emoji with variation selectors / ZWJ / skin tones (❤️ silently failed)#744
lilyshen0722 merged 2 commits into
mainfrom
fix/reaction-emoji-variation-selector

Conversation

@lilyshen0722

Copy link
Copy Markdown
Contributor

Bug (2026-07-24, reported during launch)

"Reactions can't show more than one." Root cause: SAFE_EMOJI_RE rejected ❤️.

const SAFE_EMOJI_RE = /^[\p{Emoji}‍]{1,8}$/u\p{Emoji} matches base emoji code points but not the combining marks real emoji carry: U+FE0F (variation selector), U+200D (ZWJ), skin-tone modifiers. ❤️ is U+2764 + U+FE0F, so it failed with 400 "emoji must be 1–8 emoji characters." ❤️ is in the client's reaction palette (['👍','❤️','🔥','🤔','👀','🚀']), and the frontend swallows reaction errors — so clicking ❤️ did nothing. Users reacted 👍 (a plain single code point, worked), tried ❤️ (silently failed) → "can't add a second reaction."

Verified live: curl POST ❤️ → 400; the backend count aggregation (listForMessagecount:2 for two users) and the UI count render (Playwright showed 👍 ×2) were both confirmed correct. This validation was the entire bug.

Fix

const SAFE_EMOJI_RE = /^[\p{Emoji}\u{200D}\u{FE0F}\p{Emoji_Modifier}]{1,16}$/u;

Allows variation selectors, ZWJ sequences, and skin-tone modifiers; cap raised to 16 code points for family/profession sequences.

Test

reactionController.emojiValidation.test.js❤️, 👍🏽, 👨‍👩‍👧 accepted; non-emoji still 400s. Existing reactionController suite green.

Related (separate, not in this PR)

  • Silent failures: the frontend swallows reaction errors (V2MessageBubble toggle catch) — surfacing them would have made this obvious. Worth a small follow-up.
  • Non-members can't react in public rooms (403) — a design call for publicRead pods.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DMeWzgFxsfBcjoLVLewEES

lilyshen0722 and others added 2 commits July 24, 2026 00:07
SAFE_EMOJI_RE was /^[\p{Emoji}‍]{1,8}$/u. `\p{Emoji}` does NOT match the
combining marks real emoji carry — U+FE0F (variation selector), skin-tone
modifiers — so ❤️ (U+2764 U+FE0F), which is in the client's reaction palette,
400'd with "emoji must be 1–8 emoji characters". The frontend swallows reaction
errors, so clicking ❤️ did nothing: users perceived "reactions can't show more
than one" (their obvious second reaction, love, silently failed). Confirmed live
against the API on 2026-07-24; the backend count aggregation and the UI count
render were both verified correct — this validation was the whole bug.

Fix: widen the char class to allow U+FE0F, U+200D (ZWJ sequences), and
\p{Emoji_Modifier} (skin tones); raise the cap to 16 code points for sequences.

Test: reactionController.emojiValidation.test.js — ❤️, 👍🏽, 👨‍👩‍👧 accepted;
plain non-emoji still 400s.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DMeWzgFxsfBcjoLVLewEES
The reaction toggle caught and ignored all errors, so a rejected reaction
(bad-emoji 400, non-member 403, rate-limit 429) did nothing visible. That
silence is what made the ❤️-validation bug read as "reactions can't show more
than one" — the second reaction just vanished. Now show the server message (or
a status-mapped fallback) for ~4s beneath the chips.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DMeWzgFxsfBcjoLVLewEES
@lilyshen0722
lilyshen0722 merged commit 8d22b49 into main Jul 24, 2026
10 checks passed
@lilyshen0722
lilyshen0722 deleted the fix/reaction-emoji-variation-selector branch July 24, 2026 07:23
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.

1 participant