Skip to content

[Due for payment 2026-03-19] Report - Cancel payment doesn't work and leads to blank page #85019

Closed

Description

@mitarachim

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.36-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: https://test-management.browserstack.com/projects/2219752/folder/13176792/test-cases/41237180
Email or phone of affected tester (no customers): gatantm+6210@gmail.com
Issue reported by: Applause Internal Team
Bug source: Regression TC Execution
Device used: MacOS 26.2, Safari
App Component: Chat Report View

Action Performed:

  1. Launch expensify and go to WS tab
  2. Open any WS chat and submit an expense to it
  3. Approve and Pay the expense
  4. Open the report select More > Cancel payment

Expected Result:

The payment is canceled and user sees it on the report

Actual Result:

The app is stuck on empty page. The payment is not canceled

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

Bug7100499_1773268212290.Recording__1540.mp4
Bug7100499_1773268212353.Recording__1541.mp4

View all open jobs on GitHub

Activity

  1. added
    DeployBlockerCashThis issue or pull request should block deployment
    BugSomething is broken. Auto assigns a BugZero manager.
    DeployBlockerIndicates it should block deploying the API
    on Mar 12, 2026
  2. github-actions commented on Mar 12, 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.
  3. melvin-bot commented on Mar 12, 2026

    @melvin-bot

    Triggered auto assignment to @iwiznia (DeployBlockerCash), see https://stackoverflowteams.com/c/expensify/questions/9980/ for more details.

  4. melvin-bot commented on Mar 12, 2026

    @melvin-bot

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

  5. iwiznia commented on Mar 12, 2026

    @iwiznia
    Contributor

    @MelvinBot can you investigate which PR we deployed to staging recently caused this?

  6. MelvinBot commented on Mar 12, 2026

    @MelvinBot
    Contributor

    🔍 Investigation: Which PR caused Cancel Payment → blank page?

    Summary: After investigating all 80+ PRs in the 9.3.36-0 staging release against the cancel payment flow, the most likely culprit is PR #84860 (Bump Onyx to 3.0.45), which introduced a new OnyxSnapshotCache caching layer that can serve stale data during batch Onyx updates — exactly the kind of update that cancelPayment triggers.

    Symptoms

    • User opens workspace chat → submits expense → approves & pays → selects More > Cancel payment
    • App gets stuck on blank/empty page
    • Payment is NOT canceled (action didn't complete)
    • Reproducible in staging (9.3.36-0), NOT in production
    • Platform: macOS Safari

    Primary Suspect: PR #84860 — Bump Onyx to 3.0.45

    This PR bumped react-native-onyx from 3.0.43 → 3.0.45, introducing a new OnyxSnapshotCache class that sits between useOnyx's useSyncExternalStore getSnapshot() and the actual Onyx data store.

    Why this is suspicious:

    1. cancelPayment() triggers batch Onyx updates on 4+ keys simultaneously (src/libs/actions/IOU/index.ts:10996-11086): COLLECTION.REPORT_ACTIONS, COLLECTION.REPORT (chat report), COLLECTION.REPORT (expense report — changes statusNum, stateNum, isCancelledIOU), and COLLECTION.NEXT_STEP.

    2. MoneyReportHeader subscribes to ~20 Onyx keys via useOnyx (src/components/MoneyReportHeader.tsx:226-290), all of which now use the new OnyxSnapshotCache. A single cancelPayment triggers a cascade of subscriber callbacks across all these hooks.

    3. The new cache has asymmetric invalidation (OnyxSnapshotCache.invalidateForKey): member keys invalidate upward to collection keys, but collection keys do NOT cascade downward to members. If subscriber callbacks fire sequentially during the batch update, getSnapshot() for subscriptions that haven't received their callback yet will return stale cached results from OnyxSnapshotCache.

    4. Potential for undefined/inconsistent state: If the cache is invalidated but the new value hasn't been written to OnyxCache yet, getSnapshot() could return undefined, causing MoneyReportHeader and ReportScreen to render with missing data — explaining the blank page.

    5. Selector equality semantics changed: For hooks with selectors, values are now compared by reference (===) instead of the previous comparison method. This could cause certain selectors in MoneyReportHeader to miss updates they previously would have caught.

    PRs Ruled Out

    I investigated the following PRs and confirmed they do NOT modify the cancel payment flow:

    PR Title Verdict
    #79944 refactor trackExpense Only draft transaction cleanup — cancelPayment untouched
    #84512 Add 'Move to report' in More menu Purely additive — cancel payment logic unchanged
    #82905 Prevent dead-end when closing account Only workspace deletion guards
    #81917 Refine category receipt interaction Only workspace category settings
    #84060 Avoid subscribing to all policies in ReportActionList Performance-only — no blank-page conditions based on policy
    #84734 Optimize LHN renderItem and sidebar sorting Only LHN sidebar display — doesn't touch ReportScreen
    #84792 Fix breakdown rows toggling Only MoneyReportView/MoneyRequestReportTransactionList display

    Additional Context

    The cancel payment flow in MoneyReportHeader.tsx:1496-1509 uses showConfirmModal from the useConfirmModal hook. On web, this modal uses shouldHandleNavigationBack: true, which pushes a browser history state and pops it with window.history.back() on close. On Safari specifically, this history manipulation could interact poorly with the Onyx cache changes, potentially navigating the user away before the confirmation completes — explaining both the blank page AND the payment not being canceled.

    Recommended Next Steps

    1. Quick validation: Try reverting react-native-onyx from 3.0.45 back to 3.0.43 and test cancel payment on Safari to confirm/deny this hypothesis.
    2. Check the Onyx changelog between 3.0.43 and 3.0.45 for specific cache-related changes.
    3. If confirmed, the Onyx team should review OnyxSnapshotCache.invalidateForKey() to ensure batch Onyx.merge operations invalidate all relevant cache entries atomically before any getSnapshot() calls.

    Confidence: Medium — Code evidence strongly supports this hypothesis, but runtime logs or a revert test are needed for definitive confirmation.

  7. 7 remaining items

  8. m-natarajan commented on Mar 12, 2026

    @m-natarajan

    Not repro, Chrome / v9.3.36-6

    Screen.Recording.2026-03-12.at.17.37.20.mp4
  9. luacmartins commented on Mar 12, 2026

    @luacmartins
    Contributor

    Fixed. Closing.

  10. added
    Awaiting PaymentAuto-added when associated PR is deployed to production
    and removed on Mar 12, 2026
  11. changed the title [-]Report - Cancel payment doesn't work and leads to blank page[/-] [+][Due for payment 2026-03-19] Report - Cancel payment doesn't work and leads to blank page[/+] on Mar 12, 2026
  12. melvin-bot commented on Mar 12, 2026

    @melvin-bot

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

  13. melvin-bot commented on Mar 12, 2026

    @melvin-bot

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.3.36-10 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-03-19. 🎊

  14. melvin-bot commented on Mar 12, 2026

    @melvin-bot

    @iwiznia 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 12, 2026

    @melvin-bot

    Triggered auto assignment to @mallenexpensify (Awaiting Payment)

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