Skip to content

[Due for payment 2026-04-02] [Due for payment 2026-04-01] [RCA #77636] Chat - Error when opening chat with non-existing user #86221

Closed

Description

@nlemma

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.3.43-0
Reproducible in staging?: Yes
Reproducible in production?: No
If this was caught during regression testing, add the test name, ID and link from BrowserStack: #84391
Email or phone of affected tester (no customers): snodijosdnjoijiosnj@gmail.com
Issue reported by: Applause Internal Team
Bug source: Exploratory - Significant User Experience Deterioration
Device used: Mac 26.2 / Chrome
App Component: Chat Report View

Action Performed:

  1. Go to staging.new.expensify.com
  2. Open search.
  3. Enter email that does not have Expensify account.
  4. Tap on the user.

Expected Result:

Chat will open without issue.

Actual Result:

Chat is grayed out and opened with "Email not found" error.

This issue also happens when opening chat with non-existing user from FAB > Start chat.

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

Bug7111682_1774354155398.1.mp4

View all open jobs on GitHub

Issue OwnerCurrent Issue Owner: @mallenexpensify

Activity

  1. added
    DeployBlockerCashThis issue or pull request should block deployment
    BugSomething is broken. Auto assigns a BugZero manager.
    on Mar 24, 2026
  2. melvin-bot commented on Mar 24, 2026

    @melvin-bot

    You have been assigned to this deploy blocker because you recently merged this PR: #84391

  3. melvin-bot commented on Mar 24, 2026

    @melvin-bot

    💬 A slack conversation has been started in #expensify-open-source

  4. github-actions commented on Mar 24, 2026

    @github-actions
    Contributor

    👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:

    1. Identify the pull request that introduced this issue and revert it.
    2. Find someone who can quickly fix the issue.
    3. Fix the issue yourself.
  5. OSBotify commented on Mar 24, 2026

    @OSBotify
    Contributor

    Investigation Summary

    Classification: Frontend bug
    Causing PR: #77636 - "Part 1: Remove Onyx.connect() for the key: ONYXKEYS.PERSONAL_DETAILS_LIST in src/libs/actions/Report.ts" by @narefyev91 (High confidence)
    Related Issues: None

    Recommendation: REVERT

    PR #77636 should be reverted. The PR introduced a breaking change in how navigateToAndOpenReportWithAccountIDs handles personal details, which breaks the flow for creating chats with new users who do not have personal details loaded yet.

    Labels: This is a frontend bug. PR #77636 is an App PR that needs to be reverted. Keeping DeployBlockerCash label as-is.

    Detailed Analysis

    Evidence

    The issue reports that opening a chat with a non-existing user (email without Expensify account) from search or FAB > Start chat results in an "Email not found" error and a grayed-out chat. This is reproducible on staging (v9.3.43-0) but NOT on production.

    PR #77636 was merged on March 23, 2026 and is included in the staging deploy. The PR modified how personal details are passed to navigateToAndOpenReportWithAccountIDs and related functions.

    Verification

    File affected by the bug: /home/runner/_work/App/App/src/libs/actions/Report/index.ts (lines 2085-2124)

    PR #77636 modifies this file: Confirmed - it changes navigateToAndOpenReportWithAccountIDs function and adds a personalDetails parameter.

    The breaking change: In /home/runner/_work/App/App/src/components/PromotedActionsBar.tsx line 87, the function is called WITHOUT passing personalDetails:

    navigateToAndOpenReportWithAccountIDs([accountID], currentUserAccountID, introSelected, betas);

    Inside navigateToAndOpenReportWithAccountIDs (Report/index.ts lines 2101-2112), when personalDetails is not passed, it falls back to allPersonalDetails. However, the code filters out any participant whose login cannot be found:

    const participants = participantAccountIDs
        .map((accountID): ParticipantInfo | null => {
            const personalDetail = detailsToUse?.[accountID];
            if (!personalDetail?.login) {
                return null;  // Filters out this participant
            }
            return {
                login: personalDetail.login,
                accountID,
            };
        })
        .filter((p): p is ParticipantInfo => p !== null);

    For new users or users without Expensify accounts, personalDetail?.login will be undefined, causing them to be filtered out. This results in calling openReport with an empty or incomplete participants array, which causes the "Email not found" error.

    Root Cause

    PR #77636 attempted to remove the dependency on Onyx.connect() for personal details, but missed updating all call sites. Specifically:

    1. PromotedActionsBar.tsx line 87 does not pass personalDetails to navigateToAndOpenReportWithAccountIDs
    2. WorkspaceWorkflowsPayerPage.tsx line 361 also does not pass personalDetails
    3. When personal details are not passed and fall back to allPersonalDetails, the new filtering logic incorrectly excludes participants who do not yet have personal details loaded

    This breaks the flow for creating chats with new or non-existing users.

  6. MelvinBot commented on Mar 24, 2026

    @MelvinBot
    Contributor

    Proposal

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

    When a user searches for an email that doesn't have an Expensify account and taps on that user, the chat opens grayed out with an "Email not found" error. This happens from both Search and FAB > Start Chat on staging (v9.3.43-0) but not on production.

    What is the root cause of that problem?

    PR #77636 ("Part 1: Remove Onyx.connect() for PERSONAL_DETAILS_LIST in Report.ts"), merged March 23, changed how openReport receives participant data. Previously, navigateToAndOpenReport passed only participantLoginList (the email strings) to openReport, and participantAccountIDList defaulted to [] — meaning the accountIDList API parameter was always empty for new chats.

    After PR #77636, participants are passed as {login, accountID} objects. The accountIDs come from getAccountIDsByLogins(), which calls generateAccountID() (a client-side hash) for users that don't exist in personal details. openReport then extracts both participantLoginList and participantAccountIDList from these objects:

    // src/libs/actions/Report/index.ts:1325-1326
    const participantLoginList = participants.map((p) => p.login);
    const participantAccountIDList = participants.map((p) => p.accountID)
        .filter((id): id is number => id !== undefined);
    

    This means the OpenReport API call now sends accountIDList containing a synthetic client-side hash ID (e.g., accountIDList: "2847163952") alongside the email in emailList. The backend receives this bogus accountID, can't find it, and returns an errorFields.createChat error with "Email not found". The OfflineWithFeedback component then grays out the chat due to isAddError (pendingAction=add + hasErrors=true).

    Before PR #77636: emailList: "newuser@gmail.com", accountIDList: "" → backend creates user from email → works.
    After PR #77636: emailList: "newuser@gmail.com", accountIDList: "2847163952" → backend tries to look up fake accountID → "Email not found".

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

    In openReport (src/libs/actions/Report/index.ts), filter out optimistic/synthetic accountIDs from participantAccountIDList before they reach the API parameters. Only include accountIDs for users that actually exist in personal details:

    const participantAccountIDList = participants
        .map((p) => p.accountID)
        .filter((id): id is number => id !== undefined && !!personalDetails?.[id]);
    

    This restores the pre-PR-#77636 behavior where non-existing users only send their email (via emailList) without a bogus accountID, while still correctly passing accountIDs for known/existing users.

    What alternative solutions did you explore?

    1. Don't pass accountIDs in buildParticipantInfoFromLogins: Could omit the accountID entirely when building from logins, but this would also remove accountIDs for existing users where having the ID is useful.
    2. Filter in navigateToAndOpenReport instead: Could check personal details there before building participants, but the fix is better centralized in openReport since navigateToAndOpenReportWithAccountIDs has a similar issue (it silently drops non-existing users from the participants array entirely).

    Next Steps for Contributor+ team: Reply with @MelvinBot implement this to create a draft PR, @MelvinBot <your feedback> to refine this analysis, or explain why you are rejecting Melvin's proposal.

  7. parasharrajat commented on Mar 24, 2026

    @parasharrajat
    Member

    @lorretheboy Can you check this?

  8. justinpersaud commented on Mar 24, 2026

    @justinpersaud
    Contributor
  9. 13 remaining items

  10. added
    Awaiting PaymentAuto-added when associated PR is deployed to production
    and removed on Mar 25, 2026
  11. changed the title [-][RCA #77636] Chat - Error when opening chat with non-existing user[/-] [+][Due for payment 2026-04-01] [RCA #77636] Chat - Error when opening chat with non-existing user[/+] on Mar 25, 2026
  12. melvin-bot commented on Mar 25, 2026

    @melvin-bot

    Reviewing label has been removed, please complete the "BugZero Checklist".

  13. melvin-bot commented on Mar 25, 2026

    @melvin-bot

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.3.43-3 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

    If no regressions arise, payment will be issued on 2026-04-01. 🎊

  14. melvin-bot commented on Mar 25, 2026

    @melvin-bot

    @AndrewGable The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]

  15. melvin-bot commented on Mar 25, 2026

    @melvin-bot

    Triggered auto assignment to @mallenexpensify (Awaiting Payment)

  16. changed the title [-][Due for payment 2026-04-01] [RCA #77636] Chat - Error when opening chat with non-existing user[/-] [+][Due for payment 2026-04-02] [Due for payment 2026-04-01] [RCA #77636] Chat - Error when opening chat with non-existing user[/+] on Mar 26, 2026
  17. melvin-bot commented on Mar 26, 2026

    @melvin-bot

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.3.48-2 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

    If no regressions arise, payment will be issued on 2026-04-02. 🎊

  18. melvin-bot commented on Mar 26, 2026

    @melvin-bot

    @AndrewGable @mallenexpensify The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]

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

Metadata

Metadata

Labels

Awaiting PaymentAuto-added when associated PR is deployed to productionBugSomething is broken. Auto assigns a BugZero manager.EngineeringWeeklyKSv2

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions