Skip to content

Create expense opens when navigate back from referral page #100645

Closed

Description

@applause-bot

If you haven’t already, check out our contributing guidelines for onboarding. To join our Slack channel, fill out this form.


Version Number: 9.4.74-0
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught during regression testing, add the test name, ID and link from BrowserStack: #99947
Email or phone of affected tester (no customers): applausetester+gm1038529@applause.expensifail.com
Issue reported by: Applause Internal Team
Bug source: Pull Request QA execution
Device used: windows 10/chrome
App Component: Other

Action Performed:

  1. Go to staging.new.expensify.com
  2. Open FAB > Create expense > Manual.
  3. Click To.
  4. Click Referral banner at the bottom.
  5. Click RHP back button.

Expected Result:

The previous page, which is Participant list will open.

Actual Result:

Create expense page opens.

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

Bug7254532_1788899824135.Recording__1548.mp4

View all open jobs on GitHub

Applause Internal Information
Exported by: Svetlana Lazutkina
Bug ID: 7254532

Issue OwnerCurrent Issue Owner: @thelullabyy

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Sep 8, 2026
  2. applause-bot commented on Sep 8, 2026

    @applause-bot
    Author

    While Applause doesn't embed attachments for this bug, here are the links for quick view:
    https://platform.applause.com/services/links/v1/external/e0b4c8bc0898ffbf04c78499d905f2341854451ff3d97a21e774f9838e3c6778

  3. MelvinBot commented on Sep 8, 2026

    @MelvinBot
    Contributor

    Proposal

    What is the root cause of that problem?

    In the new manual expense flow the participant list is not a page — it's a right-docked modal rendered inside the "Create expense" screen, driven by React state (ParticipantPicker/index.tsx:23-33). Because it has no route, going back from the referral page can only ever land on "Create expense". The back button itself is correct.

    Expensify/App#99947 already anticipated this and added a mitigation: close the picker before navigating to the referral page, then reopen it when the screen refocuses. That reopen never runs. Its guard bails out first:

    IOURequestStepConfirmation.tsx:404

    if (!activeTransactionID || hasSelectedParticipants) {
        return;
    }

    hasSelectedParticipants is always true on this path, because the same component auto-assigns a default recipient (default workspace expense chat, or self DM) with selected: true on mount (IOURequestStepConfirmation.tsx:524-545). So the guard throws the reopen away and the user sees the expense form.

    That auto-assignment is also why the reporter had to click "To" (the picker didn't auto-open) — the very state that forces step 3 of the repro is the state that kills the restore.

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

    Drop the hasSelectedParticipants condition from the focus-listener guard at IOURequestStepConfirmation.tsx:399-409, keeping only the activeTransactionID null check, and remove it from the effect's dependency array.

    The stated purpose of that condition — stopping an unrelated RHP round trip from slamming the picker open — is already served by shouldReopenParticipantPickerOnFocusRef on the line above it. That ref is set in exactly one place, closeParticipantPickerForReferralNavigation, and only when the picker was actually visible, so unrelated refocuses already return early. The recipient check is redundant and unconditionally true, which is what makes the code unreachable.

    The existing regression test passes only because its fixture seeds participants: [] with no default policy or self DM in Onyx (IOURequestStepConfirmationPageTest.tsx:1537-1574), so it never covers an account with a default workspace — the common production case. Add a case with a default recipient present.

    What alternative solutions did you explore? (Optional)

    Making the participant picker its own route again, so back works structurally instead of via a state-restore hack. This area has regressed three times in a row on the same design (Expensify/App#87920 converted the route to a modal, Expensify/App#94546 added a partial close-before-navigate, Expensify/App#99947 added the reopen, and now this issue). Worth considering separately, but it is far larger than this fix needs to be.

    Investigation details

    Full chain

    1. FAB > Create expense > Manual → one route, MONEY_REQUEST.CREATE → IOURequestStartPage.tsx:224 embeds the confirmation step inline.
    2. On mount the default recipient is written into the draft with selected: true, so hasSelectedParticipants (line 347) is true and auto-open is suppressed.
    3. Clicking "To" only flips local state — MoneyRequestConfirmationList.tsx:441-453 calls onOpenParticipantPicker() when the beta is on, versus a real Navigation.navigate(...STEP_PARTICIPANTS) when it's off. No route, no history entry.
    4. The referral banner (ParticipantSelectorFooter.tsx:62-68 → ReferralProgramCTA.tsx:66-69) closes the picker, then pushes the referral RHP with backTo = the Create expense path, since getActiveRouteWithoutParams() cannot see a modal.
    5. Back → DynamicReferralDetailsPage.tsx:68-70 pops correctly to Create expense; the focus listener fires, consumes the ref, then returns at line 404. Picker stays closed.

    Ruled out

    • Stack collapse. The referral page lives in a different modal stack (RIGHT_MODAL.REFERRAL), but it's pushed above an intact money-request stack. Confirmed by the symptom itself: back lands on Create expense, not the Inbox, so the screen survived and its state is intact.
    • goBack target wrong. useDynamicBackPath correctly strips the referral/:contentType suffix. There is no participant route to target.
    • Mitigation not deployed. Expensify/App#99947 deployed to staging as 9.4.74-0 about two hours before this was filed, which is the version reported.

    Runtime repro

    An automated web run reproduced steps 1–3 (Create expense > Manual, participant list, referral banner opens). Step 4 was inconclusive: that test account had no default workspace, so the picker auto-opened rather than needing a "To" click — a different state from the report — and the run then navigated off the app entirely. The code chain above is verified statically; the focus event firing on return was not observed at runtime.

    Related issues: a quick scan of open Expensify/App issues for this symptom found no duplicates. The three prior PRs listed under alternatives are the relevant history.


    Next Steps for Contributor+ team:
    To accept: @MelvinBot implement [this](https://github.com/Expensify/App/issues/100645) to create a draft PR.
    To refine: @MelvinBot <your feedback>
    To reject: Explain why you are rejecting Melvin's proposal.


    view run · no recording available

  4. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Sep 8, 2026
  5. melvin-bot commented on Sep 8, 2026

    @melvin-bot

    Triggered auto assignment to Contributor-plus team member for initial proposal review - @bernhardoj (External)

  6. melvin-bot commented on Sep 8, 2026

    @melvin-bot

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

  7. bernhardoj commented on Sep 9, 2026

    @bernhardoj
    Contributor

    I think @thelullabyy should handle this as this is coming from their recent PR

  8. mountiny commented on Sep 9, 2026

    @mountiny
    Contributor

    @thelullabyy can you follow up as a regression please

  9. melvin-bot commented on Sep 14, 2026

    @melvin-bot

    @thelullabyy Eep! 4 days overdue now. Issues have feelings too...

  10. 23 remaining items

  11. melvin-bot commented on Nov 3, 2026

    @melvin-bot

    @thelullabyy Eep! 4 days overdue now. Issues have feelings too...

  12. melvin-bot commented on Nov 3, 2026

    @melvin-bot

    @thelullabyy Huh... This is 4 days overdue. Who can take care of this?

  13. melvin-bot commented on Nov 3, 2026

    @melvin-bot

    @thelullabyy Eep! 4 days overdue now. Issues have feelings too...

  14. melvin-bot commented on Nov 4, 2026

    @melvin-bot

    @thelullabyy Eep! 4 days overdue now. Issues have feelings too...

  15. melvin-bot commented on Nov 5, 2026

    @melvin-bot

    @thelullabyy 6 days overdue. This is scarier than being forced to listen to Vogon poetry!

  16. jeffrey-graham commented on Nov 7, 2026

    @jeffrey-graham
  17. melvin-bot commented on Nov 7, 2026

    @melvin-bot
  18. thelullabyy commented on Nov 9, 2026

    @thelullabyy
    Contributor

    Finally, I can back to this issue. Will check it today

  19. thelullabyy commented on Nov 10, 2026

    @thelullabyy
    Contributor

    The issue is no longer reproducible. I think we can close this issue cc @ikevin127 @mountiny

    Screen.Recording.2026-11-10.at.19.40.19.mov
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 contributor

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions