Skip to content

Room - App crashes when opening room avatar when workspace name has emoji #69428

Closed

Description

@jponikarchuk

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Version Number: 9.2.0-0
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught during regression testing, add the test name, ID and link from TestRail: https://test-management.browserstack.com/projects/2219752/test-runs/TR-516/41237930/864763228?q=avatar&issue_type=jira
Email or phone of affected tester (no customers): sdhshssdjiosdndjs@gmail.com
Issue reported by: Applause Internal Team
Device used: iPhone 15 Pro Max / iOS 18.6
App Component: Chat Report View

Action Performed:

  1. Launch Expensify app.
  2. Create a workspace with emoji as name.
  3. Go to #admins.
  4. Tap on the report header.
  5. Tap on the avatar.

Expected Result:

App will not crash.

Actual Result:

App crashes when opening room avatar when workspace name has emoji

Workaround:

Unknown

Platforms:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

1.mp4

View all open jobs on GitHub

Issue OwnerCurrent Issue Owner: @ahmedGaber93

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Aug 28, 2025
  2. melvin-bot commented on Aug 28, 2025

    @melvin-bot

    Triggered auto assignment to @sonialiap (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

  3. muhammad-ali-abbasi commented on Aug 28, 2025

    @muhammad-ali-abbasi

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    The app crashes when users navigate to workspace rooms (like #admins) and tap on the room avatar if the workspace name contains emojis. This completely prevents users from accessing the room avatar modal and viewing workspace details in these scenarios.

    What is the root cause of that problem?

    The crash happens because of a failing regex test in the emoji processing logic. This originates in
    https://github.com/Expensify/App/blob/main/src/components/Text.tsx#L57, where the containsOnlyCustomEmoji(children) function is called on workspace names containing emojis.

    The crash occurs in this flow:

    1. User taps room avatar → ReportAvatar renders with headerTitle={getPolicyName({report, policy})}
      https://github.com/Expensify/App/blob/main/src/pages/ReportAvatar.tsx#L32
    2. The workspace name with emojis gets passed to the Text component
      (https://github.com/Expensify/App/blob/main/src/components/Header.tsx#L77-L82)
    3. Text component calls containsOnlyCustomEmoji() to determine styling
      (https://github.com/Expensify/App/blob/main/src/components/Text.tsx#L55-L65)
    4. CRASH: The function uses CONST.REGEX.ONLY_PRIVATE_USER_AREA.test(text) which fails on certain emoji sequences
      (https://github.com/Expensify/App/blob/main/src/libs/EmojiUtils.tsx#L667-L673)

    The regex pattern /^[\uE000-\uF8FF\u{F0000}-\u{FFFFD}\u{100000}-\u{10FFFD}]+$/u
    (https://github.com/Expensify/App/blob/main/src/CONST/index.ts#L3547) crashes when processing complex emoji sequences like skin tone variations or combined emojis in workspace names.

    What changes do you think we should make in order to solve the problem?

    Add try-catch error handling in the containsOnlyCustomEmoji function to prevent regex crashes:

      // In src/libs/EmojiUtils.tsx:667-673
      function containsOnlyCustomEmoji(text?: string): boolean {
          if (!text) {
              return false;
          }
    
          try {
              const privateUseAreaRegex = CONST.REGEX.ONLY_PRIVATE_USER_AREA;
              return privateUseAreaRegex.test(text);
          } catch (error) {
              // If regex fails on complex emoji sequences, safely return false
              console.warn('Emoji regex failed for text:', text, error);
              return false;
          }
      }
    

    This ensures that if the regex processing fails on certain emoji sequences, the app gracefully falls back to treating the text
    as regular text instead of crashing.

    What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

    1. Emoji workspace name avatar test: Test opening room avatars with workspace names containing various emoji types (standard
      emojis, skin tone variations, combined sequences).
    2. Regex crash prevention test: Specifically test the containsOnlyCustomEmoji function with problematic emoji sequences that
      previously caused crashes.
    3. Header title rendering test: Verify that HeaderWithBackButton can safely render titles containing complex emoji sequences
      without crashing.
    4. ReportAvatar modal test: Test the complete flow from tapping room avatar to modal display with emoji workspace names.
    5. Cross-platform emoji handling test: Ensure emoji processing works consistently across iOS, Android, and web platforms.
    6. Edge case emoji testing: Test with empty strings, null values, and malformed emoji sequences to ensure robust error handling.

    What alternative solutions did you explore? (Optional)

    None

  4. Krishna2323 commented on Aug 28, 2025

    @Krishna2323
    Contributor

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    Room - App crashes when opening room avatar when workspace name has emoji

    What is the root cause of that problem?

    • The error happens because name.at(0) returns only the first UTF-16 code unit of an emoji (a lone surrogate), and getPathFromState throws “URI malformed” for that.

      App/src/ROUTES.ts

      Lines 1291 to 1294 in ae5f666

      WORKSPACE_AVATAR: {
      route: 'workspaces/:policyID/avatar',
      getRoute: (policyID: string, fallbackLetter?: UpperCaseCharacters) => `workspaces/${policyID}/avatar${fallbackLetter ? `?letter=${fallbackLetter}` : ''}` as const,
      },

      const isWorkspace = type === CONST.ICON_TYPE_WORKSPACE;
      const firstLetter = (name?.at(0) ?? 'A').toUpperCase() as UpperCaseCharacters;
      const onPress = () => {
      if (isWorkspace) {
      return Navigation.navigate(ROUTES.WORKSPACE_AVATAR.getRoute(String(avatarID), firstLetter));
      }
      return Navigation.navigate(ROUTES.PROFILE_AVATAR.getRoute(Number(avatarID), Navigation.getActiveRoute()));
      };

    What changes do you think we should make in order to solve the problem?

    • If the name starts with an emoji or non-ASCII, we can fall back to a valid ASCII uppercase letter.
        // Remove all chars not A-Z or 0-9 including underscore
        const asciiUppercaseMatch = workspaceName
            .normalize('NFD')
            .replace(/[^0-9a-z]/gi, '')
            .toUpperCase().at(0);
        const firstLetter = (asciiUppercaseMatch || 'A') as UpperCaseCharacters;
    • We can also use CONST.REGEX.ALPHABETIC_AND_LATIN_CHARS if needed.
      const isWorkspace = type === CONST.ICON_TYPE_WORKSPACE;
      const firstLetter = (name?.at(0) ?? 'A').toUpperCase() as UpperCaseCharacters;
      const onPress = () => {
      if (isWorkspace) {
      return Navigation.navigate(ROUTES.WORKSPACE_AVATAR.getRoute(String(avatarID), firstLetter));
      }
      return Navigation.navigate(ROUTES.PROFILE_AVATAR.getRoute(Number(avatarID), Navigation.getActiveRoute()));
      };

      App/src/libs/ReportUtils.ts

      Lines 2690 to 2694 in ae5f666

      // Remove all chars not A-Z or 0-9 including underscore
      const alphaNumeric = workspaceName
      .normalize('NFD')
      .replace(/[^0-9a-z]/gi, '')
      .toUpperCase();
    • OPTIONAL: Use encodeURIComponent for the fallbackLetter.

    What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

    N/A

    What alternative solutions did you explore? (Optional)

    Result

  5. Krishna2323 commented on Aug 28, 2025

    @Krishna2323
    Contributor

    PROPOSAL UPDATED

    • Added alternative solution
  6. Krishna2323 commented on Aug 28, 2025

    @Krishna2323
    Contributor

    PROPOSAL UPDATED

    • Update the proposal to use the same approach as in getDefaultWorkspaceAvatar
    • NOTE: The edit was made before the proposal above
  7. daledah commented on Aug 30, 2025

    @daledah
    Contributor

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    App crashes when opening room avatar when workspace name has emoji

    What is the root cause of that problem?

    When workspace has emoji as first character, we pass it to url here:

    const isWorkspace = type === CONST.ICON_TYPE_WORKSPACE;
    const firstLetter = (name?.at(0) ?? 'A').toUpperCase() as UpperCaseCharacters;
    const onPress = () => {
    if (isWorkspace) {
    if (reportID) {
    Navigation.navigate(ROUTES.REPORT_AVATAR.getRoute(reportID, String(avatarID)));
    return;
    }
    return Navigation.navigate(ROUTES.WORKSPACE_AVATAR.getRoute(String(avatarID), firstLetter));
    }
    return Navigation.navigate(ROUTES.PROFILE_AVATAR.getRoute(Number(avatarID), Navigation.getActiveRoute()));
    };

    There's several emojis that has a lone surrogate. This makes encodeURIComponent throws error when calling getPathFromState here

    const currentPath = getPathFromState(state, linkingConfig.config);

    What changes do you think we should make in order to solve the problem?

    Defaulting invalid characters to letter A can lead to incorrect behaviour where we display the A avatar, while the workspace avatar should use the default one, like in workspace overview page:

    Image

    Instead we should use String.toWellFormed to replace all lone surrogates to Unicode replacement character U+FFFD, which can be encoded.

    This method is still new, so we can use one of its polyfill or implement a util function similar to it.

    What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

    For main solution, add unit test for newly added utils.

    What alternative solutions did you explore? (Optional)

    The implementation of firstLetter here

    const firstLetter = (name?.at(0) ?? 'A').toUpperCase() as UpperCaseCharacters;

    And its usage here

    const avatarURL = policyAvatarURL || getDefaultWorkspaceAvatar(policy?.name ?? fallbackLetter);

    Was added in #68015 to fix #67958. However, after #68839 was merged, we pass reportID to ReportActionAvatarSubscript now:

    So we'll always navigate to report avatar page:

    if (reportID) {
    Navigation.navigate(ROUTES.REPORT_AVATAR.getRoute(reportID, String(avatarID)));
    return;
    }

    Which also accidentaly fixes #68839, effectively voids the usage of firstLetter above now. So we can remove that prop and its usage from ReportActionAvatar and WorkspaceAvatar.

    Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

  8. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Sep 1, 2025
  9. melvin-bot commented on Sep 1, 2025

    @melvin-bot

    Unable to auto-create job on Upwork. The BZ team member should create it manually for this issue.

  10. added
    Help WantedApply this label when an issue is open to proposals by contributors
    on Sep 1, 2025
  11. 12 remaining items

  12. ahmedGaber93 commented on Sep 11, 2025

    @ahmedGaber93
    Contributor

    Not overdue, already updated 8 minutes ago #69428 (comment)

  13. mvtglobally commented on Sep 13, 2025

    @mvtglobally

    Issue not reproducible during KI retests. (First week)

  14. ahmedGaber93 commented on Sep 15, 2025

    @ahmedGaber93
    Contributor

    @sonialiap I think we should add "need to reproduction" label or close this as I am also not able to reproduce #69428 (comment)

  15. mvtglobally commented on Sep 20, 2025

    @mvtglobally

    Issue not reproducible during KI retests. (Second week)

  16. ahmedGaber93 commented on Sep 20, 2025

    @ahmedGaber93
    Contributor

    Also, not able to reproduce.

  17. ahmedGaber93 commented on Sep 20, 2025

    @ahmedGaber93
    Contributor
  18. melvin-bot commented on Sep 23, 2025

    @melvin-bot

    @ahmedGaber93 Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

  19. ahmedGaber93 commented on Sep 24, 2025

    @ahmedGaber93
    Contributor
  20. sonialiap commented on Sep 24, 2025

    @sonialiap
    Contributor

    I think we can close this as not reproducible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributorHelp WantedApply this label when an issue is open to proposals by contributors

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions