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-05-20] [$250] Chat - Unexpected error after created a room then send message to new user via share code #85793
When clicking "Message" on a profile opened via share code, navigateToAndOpenReport is called with shouldDismissModal=false (PromotedActionsBar.tsx:84). Inside navigateToReport, this triggers:
An immediate Navigation.navigate(...) on line 1967 (the else if branch)
A secondNavigation.navigate(...) inside a setTimeout on lines 1970-1972 that always runs regardless of the shouldDismissModal flag
The setTimeout block was added as a workaround for composer focus issues when dismissing RHP modals, but it unconditionally executes for all callers. This causes the ReportScreen to navigate/re-render twice in quick succession.
The critical interaction: after creating a workspace room (step 2 in repro), AddWorkspaceRoom is queued in the sequential queue. When the user then creates a new DM via share code, OpenReport is queued next, and AddComment after that. The double navigation can cause ReportFetchHandler (ReportFetchHandler.tsx:102-105) to fire a second openReport call if the first OpenReport completes between the two navigations (flipping isOptimisticReport from true to false). This duplicate OpenReport via resolveOpenReportDuplicationConflictAction replaces the original in the queue, potentially disrupting the ordering guarantee that AddComment depends on — causing the server to receive AddComment for a report that isn't fully set up.
What changes do you think we should make in order to solve the problem?
The setTimeout navigation block in navigateToReport (lines 1970-1972) should only execute when shouldDismissModal is true, which is the case it was designed for. Wrap it in the shouldDismissModal condition:
function navigateToReport(reportID, shouldDismissModal = true) {
if (shouldDismissModal) {
Navigation.dismissModal({
callback: () => {
if (!reportID) { return; }
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID));
},
});
// Workaround: when RHP modal gets hidden, composer focus breaks — delayed navigation fixes this
setTimeout(() => {
Navigation.isNavigationReady().then(() => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID)));
}, 0);
} else if (reportID) {
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID));
}
}
This eliminates the double navigation for the share code → DM flow while preserving the existing composer-focus workaround for the modal-dismiss path.
What alternative solutions did you explore? (Optional)
An alternative would be adding a guard in ReportFetchHandler to debounce or skip duplicate openReport calls for the same reportID within a short window. However, fixing the root cause in navigateToReport is simpler and avoids the double navigation 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.
The PR for this issue introduced #94571 when its shared navigateToReport() change separated modal dismissal from report navigation. Firefox could deliver the dismissal’s popstate after React Navigation’s 100ms pending timeout, causing the app to return to the previous route.
Activity
MelvinBot commentedon Apr 13, 2026
Proposal
What is the root cause of that problem?
There is a bug in the
navigateToReportfunction atsrc/libs/actions/Report/index.ts:1970-1972that causes double navigation to the same report screen.When clicking "Message" on a profile opened via share code,
navigateToAndOpenReportis called withshouldDismissModal=false(PromotedActionsBar.tsx:84). InsidenavigateToReport, this triggers:Navigation.navigate(...)on line 1967 (theelse ifbranch)Navigation.navigate(...)inside asetTimeouton lines 1970-1972 that always runs regardless of theshouldDismissModalflagThe
setTimeoutblock was added as a workaround for composer focus issues when dismissing RHP modals, but it unconditionally executes for all callers. This causes theReportScreento navigate/re-render twice in quick succession.The critical interaction: after creating a workspace room (step 2 in repro),
AddWorkspaceRoomis queued in the sequential queue. When the user then creates a new DM via share code,OpenReportis queued next, andAddCommentafter that. The double navigation can causeReportFetchHandler(ReportFetchHandler.tsx:102-105) to fire a secondopenReportcall if the firstOpenReportcompletes between the two navigations (flippingisOptimisticReportfromtruetofalse). This duplicateOpenReportviaresolveOpenReportDuplicationConflictActionreplaces the original in the queue, potentially disrupting the ordering guarantee thatAddCommentdepends on — causing the server to receiveAddCommentfor a report that isn't fully set up.What changes do you think we should make in order to solve the problem?
The
setTimeoutnavigation block innavigateToReport(lines 1970-1972) should only execute whenshouldDismissModalistrue, which is the case it was designed for. Wrap it in theshouldDismissModalcondition:This eliminates the double navigation for the share code → DM flow while preserving the existing composer-focus workaround for the modal-dismiss path.
What alternative solutions did you explore? (Optional)
An alternative would be adding a guard in
ReportFetchHandlerto debounce or skip duplicateopenReportcalls for the same reportID within a short window. However, fixing the root cause innavigateToReportis simpler and avoids the double navigation entirely.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.melvin-bot commentedon Apr 13, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @brunovjk (
External)42 remaining items
melvin-bot commentedon May 19, 2026
Triggered auto assignment to @mallenexpensify (
Awaiting Payment)melvin-bot commentedon May 20, 2026
Payment Summary
Upwork Job
BugZero Checklist (@mallenexpensify)
mallenexpensify commentedon May 22, 2026
Payment Summary
Contributor: @neerajbachani paid $250 via Upwork
Contributor+: @brunovjk due $250 via NewDot
@neerajbachani can you please accept the job below? Please reply here and tag me once you have.
@neerajbachani in a dedicated post, can you enter your Upwork details? I'm hoping they'll be saved to send you auto-offers in the future. Thx
neerajbachani commentedon May 22, 2026
@mallenexpensify I’ve accepted the Upwork offer.
neerajbachani commentedon May 22, 2026
Contributor details
Your Expensify account email: neerajbachani2003@gmail.com
Upwork Profile Link: https://www.upwork.com/freelancers/~011e784d9b972c347c
melvin-bot commentedon May 22, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
mallenexpensify commentedon May 22, 2026
Thanks @neerajbachani paid, summary updated above. Thx.
laurenreidexpensify commentedon May 25, 2026
$250 approved for @brunovjk
nyomanjyotisa commentedon Jul 23, 2026
The PR for this issue introduced #94571 when its shared
navigateToReport()change separated modal dismissal from report navigation. Firefox could deliver the dismissal’spopstateafter React Navigation’s 100ms pending timeout, causing the app to return to the previous route.Fixed in #95980.