You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Due for payment 2026-04-02] [Due for payment 2026-04-01] [RCA #77636] Expense - After leaving system message thread, account avatar changes to fallback avatar #86239
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:#77636 Email or phone of affected tester (no customers):jiosdjnoisdjniojsdiosi@gmail.com Issue reported by: Applause Internal Team Bug source: Exploratory - Significant User Experience Deterioration Device used: Mac 26.2 / Chrome App Component: Money Requests
Action Performed:
Go to staging.new.expensify.com
Go to workspace chat.
Create an expense.
Open the report.
Click Amount.
Edit the amount and save it.
Hover over amount edit system message.
Click 3-dot menu > Leave thread.
Go to Account.
Expected Result:
After leaving system message thread, account avatar will not change to fallback avatar.
Actual Result:
After leaving system message thread, account avatar changes to fallback avatar.
Skeleton loader is shown next to fallback avatar.
👋 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:
Identify the pull request that introduced this issue and revert it.
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 @lorretheboy (High confidence) Related Issues: None
Recommendation: REVERT
PR #77636 should be reverted to restore the correct behavior. The PR refactored openReport to require a personalDetails parameter but failed to update all call sites, causing the avatar to display as a fallback after leaving a thread.
Labels: No label changes needed. This is a frontend bug caused by an App PR, so DeployBlockerCash should remain.
📋 Detailed Analysis
Evidence
PR #77636 modified the openReport function to accept a personalDetails parameter (line 1309 in src/libs/actions/Report/index.ts). This parameter is optional in the type definition but critical for properly displaying user avatars.
The PR updated most call sites to pass personalDetails, but missed two critical locations in src/pages/inbox/ReportScreen.tsx:
Line 567: openReport({reportID: reportIDFromRoute, introSelected, reportActionID: reportActionIDFromRoute, betas});
Line 704: openReport({reportID, introSelected, betas});
Both calls are missing the personalDetails parameter.
When a user leaves a thread and then navigates to another page (like Account), the ReportScreen component calls openReport without passing personalDetails. This causes the report to be opened without the necessary personal details data, which results in:
Avatar data being unavailable or stale
The avatar displaying as a fallback/default avatar
A skeleton loader appearing next to the fallback avatar
The issue appears when navigating to Account because the ReportScreen useEffect at line 700-709 fires when the user returns to focus the app, attempting to rejoin the thread they just left - but it does so without the personal details, corrupting the avatar display state.
Please re-state the problem that we are trying to solve in this issue.
After leaving a system message thread (e.g., an "amount edited" system message) via the 3-dot context menu, the user's account avatar changes to a fallback avatar and a skeleton loader appears. This was introduced by PR #77636.
What is the root cause of that problem?
PR #77636 refactored openReport in src/libs/actions/Report/index.ts to accept personalDetails as an explicit parameter instead of reading the module-level allPersonalDetails variable directly. Most callers were updated to pass personalDetails, but toggleSubscribeToChildReport was not.
When the user clicks "Leave thread" on a system message that has no existing child thread (childReportID is undefined), toggleSubscribeToChildReport enters its else branch (line ~3077) which creates a new optimistic report and calls openReport with newReportObject but without personalDetails:
openReport({
reportID: newChat.reportID,
introSelected,
participants, // ✅ updated
newReportObject: newChat,
parentReportActionID: ...,
betas,
// ❌ personalDetails is NOT passed
});
Inside openReport, since personalDetails is undefined, the check at line ~1617:
evaluates to true for every participant (including the current user). This causes optimistic personal details with isOptimisticPersonalDetail: true to be merged into PERSONAL_DETAILS_LIST for all participants.
Then, when the API response arrives, the HandleUnusedOptimisticID middleware (src/libs/Middleware/HandleUnusedOptimisticID.ts) calls prepareOnyxDataForCleanUpOptimisticParticipants, which finds all participants now flagged with isOptimisticPersonalDetail: true and nulls out their personal details entries. This deletes the current user's personal details from Onyx, causing the fallback avatar and skeleton loader.
What changes do you think we should make in order to solve the problem?
In toggleSubscribeToChildReport (src/libs/actions/Report/index.ts, line ~3092), pass personalDetails: allPersonalDetails in the openReport call within the else branch:
This ensures existing participants are correctly recognized as non-optimistic accounts, preventing the erroneous cleanup of their personal details.
What alternative solutions did you explore? (Optional)
An alternative would be to make openReport fall back to allPersonalDetails when personalDetails is not provided (i.e., const detailsToUse = personalDetails ?? allPersonalDetails), similar to what navigateToAndOpenReportWithAccountIDs does. However, the purpose of PR #77636 was to move away from using the module-level variable, so passing it explicitly is more consistent with the intended refactoring direction.
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.
changed the title [-]Expense - After leaving system message thread, account avatar changes to fallback avatar[/-][+][RCA #77636] Expense - After leaving system message thread, account avatar changes to fallback avatar[/+]on Mar 24, 2026
changed the title [-][RCA #77636] Expense - After leaving system message thread, account avatar changes to fallback avatar[/-][+][Due for payment 2026-04-01] [RCA #77636] Expense - After leaving system message thread, account avatar changes to fallback avatar[/+]on Mar 25, 2026
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:
@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]
changed the title [-][Due for payment 2026-04-01] [RCA #77636] Expense - After leaving system message thread, account avatar changes to fallback avatar[/-][+][Due for payment 2026-04-02] [Due for payment 2026-04-01] [RCA #77636] Expense - After leaving system message thread, account avatar changes to fallback avatar[/+]on Mar 26, 2026
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:
@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]
Activity
melvin-bot commentedon Mar 24, 2026
You have been assigned to this deploy blocker because you recently merged this PR: #77636
melvin-bot commentedon Mar 24, 2026
💬 A slack conversation has been started in #expensify-open-source
github-actions commentedon Mar 24, 2026
👋 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:
OSBotify commentedon Mar 24, 2026
🔍 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 @lorretheboy (High confidence)
Related Issues: None
Recommendation: REVERT
PR #77636 should be reverted to restore the correct behavior. The PR refactored
openReportto require apersonalDetailsparameter but failed to update all call sites, causing the avatar to display as a fallback after leaving a thread.Labels: No label changes needed. This is a frontend bug caused by an App PR, so
DeployBlockerCashshould remain.📋 Detailed Analysis
Evidence
PR #77636 modified the
openReportfunction to accept apersonalDetailsparameter (line 1309 insrc/libs/actions/Report/index.ts). This parameter is optional in the type definition but critical for properly displaying user avatars.The PR updated most call sites to pass
personalDetails, but missed two critical locations insrc/pages/inbox/ReportScreen.tsx:openReport({reportID: reportIDFromRoute, introSelected, reportActionID: reportActionIDFromRoute, betas});openReport({reportID, introSelected, betas});Both calls are missing the
personalDetailsparameter.Verification
I confirmed that:
openReportfunction signature to includepersonalDetailsas a parametersrc/pages/inbox/ReportScreen.tsxdoes NOT retrieve or usepersonalDetailsfrom OnyxpersonalDetails, theopenReportfunction cannot properly look up user avatar information, resulting in the fallback avatar being displayedRoot Cause
When a user leaves a thread and then navigates to another page (like Account), the ReportScreen component calls
openReportwithout passingpersonalDetails. This causes the report to be opened without the necessary personal details data, which results in:The issue appears when navigating to Account because the ReportScreen useEffect at line 700-709 fires when the user returns to focus the app, attempting to rejoin the thread they just left - but it does so without the personal details, corrupting the avatar display state.
MelvinBot commentedon Mar 24, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
After leaving a system message thread (e.g., an "amount edited" system message) via the 3-dot context menu, the user's account avatar changes to a fallback avatar and a skeleton loader appears. This was introduced by PR #77636.
What is the root cause of that problem?
PR #77636 refactored
openReportinsrc/libs/actions/Report/index.tsto acceptpersonalDetailsas an explicit parameter instead of reading the module-levelallPersonalDetailsvariable directly. Most callers were updated to passpersonalDetails, buttoggleSubscribeToChildReportwas not.When the user clicks "Leave thread" on a system message that has no existing child thread (
childReportIDis undefined),toggleSubscribeToChildReportenters itselsebranch (line ~3077) which creates a new optimistic report and callsopenReportwithnewReportObjectbut withoutpersonalDetails:Inside
openReport, sincepersonalDetailsisundefined, the check at line ~1617:evaluates to
truefor every participant (including the current user). This causes optimistic personal details withisOptimisticPersonalDetail: trueto be merged intoPERSONAL_DETAILS_LISTfor all participants.Then, when the API response arrives, the
HandleUnusedOptimisticIDmiddleware (src/libs/Middleware/HandleUnusedOptimisticID.ts) callsprepareOnyxDataForCleanUpOptimisticParticipants, which finds all participants now flagged withisOptimisticPersonalDetail: trueand nulls out their personal details entries. This deletes the current user's personal details from Onyx, causing the fallback avatar and skeleton loader.What changes do you think we should make in order to solve the problem?
In
toggleSubscribeToChildReport(src/libs/actions/Report/index.ts, line ~3092), passpersonalDetails: allPersonalDetailsin theopenReportcall within theelsebranch:This ensures existing participants are correctly recognized as non-optimistic accounts, preventing the erroneous cleanup of their personal details.
What alternative solutions did you explore? (Optional)
An alternative would be to make
openReportfall back toallPersonalDetailswhenpersonalDetailsis not provided (i.e.,const detailsToUse = personalDetails ?? allPersonalDetails), similar to whatnavigateToAndOpenReportWithAccountIDsdoes. However, the purpose of PR #77636 was to move away from using the module-level variable, so passing it explicitly is more consistent with the intended refactoring direction.Next Steps for Contributor+ team: Reply with
@MelvinBot implement thisto create a draft PR,@MelvinBot <your feedback>to refine this analysis, or explain why you are rejecting Melvin's proposal.[-]Expense - After leaving system message thread, account avatar changes to fallback avatar[/-][+][RCA #77636] Expense - After leaving system message thread, account avatar changes to fallback avatar[/+]6 remaining items
[-][RCA #77636] Expense - After leaving system message thread, account avatar changes to fallback avatar[/-][+][Due for payment 2026-04-01] [RCA #77636] Expense - After leaving system message thread, account avatar changes to fallback avatar[/+]melvin-bot commentedon Mar 25, 2026
Reviewinglabel has been removed, please complete the "BugZero Checklist".melvin-bot commentedon Mar 25, 2026
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. 🎊
melvin-bot commentedon Mar 25, 2026
@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]
melvin-bot commentedon Mar 25, 2026
Triggered auto assignment to @mallenexpensify (
Awaiting Payment)[-][Due for payment 2026-04-01] [RCA #77636] Expense - After leaving system message thread, account avatar changes to fallback avatar[/-][+][Due for payment 2026-04-02] [Due for payment 2026-04-01] [RCA #77636] Expense - After leaving system message thread, account avatar changes to fallback avatar[/+]melvin-bot commentedon Mar 26, 2026
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. 🎊
melvin-bot commentedon Mar 26, 2026
@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]