App icon indicating copy to clipboard operation
App copied to clipboard

[$250] Expense - Report loads infinitely after deleting split and opening the empty report

Open lanitochka17 opened this issue 2 months ago โ€ข 32 comments

If you havenโ€™t already, check out our contributing guidelines for onboarding and email [email protected] to request to join our Slack channel!


Version Number: 9.2.62-0 Reproducible in staging?: Y Reproducible in production?: Y If this was caught during regression testing, add the test name, ID and link from TestRail: https://test-management.browserstack.com/projects/2219752/test-runs/TR-2116/folder/13176670/41237133/1030266308 Email or phone of affected tester (no customers): [email protected] Issue reported by: Applause - Internal Team

Action Performed:

  1. Go to staging.new.expensify.com
  2. Go to workspace chat
  3. Create an expense
  4. Open the expense report
  5. Click More > Split
  6. Click Save
  7. Open any split
  8. Click Report field > Create report
  9. Go back to workspace chat
  10. Right click on the report with one split > Delete
  11. Delete the report
  12. Click on the empty report

Expected Result:

The empty report will open

Actual Result:

Report loads infinitely after deleting split and opening the empty report

Workaround:

Unknown

Platforms:

Select the officially supported platforms where the issue was reproduced:

  • [x] Android: App
  • [x] Android: mWeb Chrome
  • [x] iOS: App
  • [x] iOS: mWeb Safari
  • [x] iOS: mWeb Chrome
  • [x] Windows: Chrome
  • [x] MacOS: Chrome / Safari
  • [x] MacOS: Desktop
Platforms Tested: On which of our officially supported platforms was this issue tested:
  • [ ] Android: App
  • [ ] Android: mWeb Chrome
  • [ ] iOS: App
  • [ ] iOS: mWeb Safari
  • [ ] iOS: mWeb Chrome
  • [ ] Windows: Chrome
  • [ ] MacOS: Chrome / Safari
  • [ ] MacOS: Desktop

Screenshots/Videos

Add any screenshot/video evidence

https://github.com/user-attachments/assets/abbfb250-68fa-4ee9-a533-50f661f374be

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021992713496560374472
  • Upwork Job ID: 1992713496560374472
  • Last Price Increase: 2025-12-21
Issue OwnerCurrent Issue Owner: @hoangzinh

lanitochka17 avatar Nov 21 '25 18:11 lanitochka17

Triggered auto assignment to @VictoriaExpensify (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

melvin-bot[bot] avatar Nov 21 '25 18:11 melvin-bot[bot]

๐Ÿšจ Edited by proposal-police: This proposal was edited at 2025-11-25 13:11:11 UTC.

Proposal

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

Report loads infinitely after deleting split and opening the empty report

What is the root cause of that problem?

When user deletes a report with split expenses, all transactions are removed from the report. And the shouldWaitForTransactions function had this logic:

  • Since transactions.length === 0 AND report.total !== 0, the condition evaluated to true
  • This caused shouldWaitForTransactions to return true

https://github.com/Expensify/App/blob/4468cb2a719511355dbabcf750dfe9e051e35829/src/libs/MoneyRequestReportUtils.ts#L116-L126

Thus, the skeleton loading screen shows infinitely here

https://github.com/Expensify/App/blob/74d28a7eccdc58ead12db528ae2cbdde2a5c7a9c/src/pages/home/ReportScreen.tsx#L960

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

We can update shouldWaitForTransactions function to use a more reliable condition for determining if data is still loading

function shouldWaitForTransactions(report: OnyxEntry<Report>, transactions: Transaction[] | undefined, reportMetadata: OnyxEntry<ReportMetadata>) {
    const isTransactionDataReady = transactions !== undefined;
    const isTransactionThreadView = isReportTransactionThread(report);
    // Don't wait for transactions if the report is being deleted
    const isReportBeingDeleted = report?.pendingFields?.preview === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
    // If we have no transactions and the report has been loaded at least once, don't wait
    // This handles the case where a report was deleted and still has a total value but no transactions
    const hasLoadedReportActions = reportMetadata?.hasOnceLoadedReportActions;
    const isStillLoadingData = transactions?.length === 0 && !hasLoadedReportActions && !!reportMetadata?.isLoadingInitialReportActions;

    const result = (
        (isMoneyRequestReport(report) || isInvoiceReport(report)) &&
        (!isTransactionDataReady || isStillLoadingData) &&
        !isTransactionThreadView &&
        !isReportBeingDeleted &&
        report?.pendingFields?.createReport !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD
    );

    return result;
}

https://github.com/Expensify/App/blob/4468cb2a719511355dbabcf750dfe9e051e35829/src/libs/MoneyRequestReportUtils.ts#L116-L126

What alternative solutions did you explore? (Optional)

Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

lorretheboy avatar Nov 21 '25 19:11 lorretheboy

Yeah we should fix this

VictoriaExpensify avatar Nov 23 '25 21:11 VictoriaExpensify

Job added to Upwork: https://www.upwork.com/jobs/~021992713496560374472

melvin-bot[bot] avatar Nov 23 '25 21:11 melvin-bot[bot]

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

melvin-bot[bot] avatar Nov 23 '25 21:11 melvin-bot[bot]

@lorretheboy Thanks for posting proposal. Can you help me understand why "the report metadata is NOT cleaned up" causes report loads infinite? TY

hoangzinh avatar Nov 25 '25 11:11 hoangzinh

I updated the proposal to follow new approach, the previous solution works for the first time but will break again if we clear the cache. Could you please re-review it? @hoangzinh

lorretheboy avatar Nov 25 '25 13:11 lorretheboy

Since transactions.length === 0 AND report.total !== 0, the condition evaluated to true

@lorretheboy, do you think we can optimistically update report.total to equal 0 in this case to fix this issue?

hoangzinh avatar Nov 27 '25 14:11 hoangzinh

๐Ÿ“ฃ It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? ๐Ÿ’ธ

melvin-bot[bot] avatar Nov 30 '25 16:11 melvin-bot[bot]

@hoangzinh Whoops! This issue is 2 days overdue. Let's get this updated quick!

melvin-bot[bot] avatar Dec 01 '25 01:12 melvin-bot[bot]

Awaiting proposals.

cc @lorretheboy

hoangzinh avatar Dec 01 '25 07:12 hoangzinh

No new approach from my side, I only figure out the solution by update the shouldWaitForTransactions @hoangzinh

lorretheboy avatar Dec 01 '25 14:12 lorretheboy

@lorretheboy Uhm, do you think we should also delete the money report instead of leaving it as an empty report in this case?

Image

hoangzinh avatar Dec 03 '25 22:12 hoangzinh

@hoangzinh I'm not sure tbh, maybe we can ask internal team about this?

lorretheboy avatar Dec 04 '25 12:12 lorretheboy

@hoangzinh @VictoriaExpensify this issue was created 2 weeks ago. Are we close to approving a proposal? If not, what's blocking us from getting this issue assigned? Don't hesitate to create a thread in #expensify-open-source to align faster in real time. Thanks!

melvin-bot[bot] avatar Dec 05 '25 21:12 melvin-bot[bot]

๐Ÿ“ฃ It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? ๐Ÿ’ธ

melvin-bot[bot] avatar Dec 07 '25 16:12 melvin-bot[bot]

I think we should delete report in this case, similar with normal expense case. @VictoriaExpensify do you agree with this expectation?

https://github.com/user-attachments/assets/f6dd86e1-7984-4d2a-9573-9c7864ed7458

hoangzinh avatar Dec 08 '25 13:12 hoangzinh

@hoangzinh Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

melvin-bot[bot] avatar Dec 11 '25 23:12 melvin-bot[bot]

๐Ÿ“ฃ It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? ๐Ÿ’ธ

melvin-bot[bot] avatar Dec 14 '25 16:12 melvin-bot[bot]

Asked @VictoriaExpensify on Slack about her thoughts on https://github.com/Expensify/App/issues/75783#issuecomment-3627045881

hoangzinh avatar Dec 15 '25 09:12 hoangzinh

Asked @VictoriaExpensify on Slack about her thoughts on https://github.com/Expensify/App/issues/75783#issuecomment-3627045881

@hoangzinh If @VictoriaExpensify agreed on this comment then I want to take this issue as an external contributor by submitting the proposal.

Uzaifm127 avatar Dec 15 '25 09:12 Uzaifm127

Yes, feel free to submit your proposal @Uzaifm127.

hoangzinh avatar Dec 15 '25 10:12 hoangzinh

๐Ÿšจ Edited by proposal-police: This proposal was edited at 2025-12-17 10:12:19 UTC.

Proposal

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

The report loads infinitely after deleting a split and opening the empty report.

What is the root cause of that problem?

In the removed report, report.total is still retained and not cleared, causing isStillLoadingData to remain true, which makes the shouldWaitForTransactions function return true

https://github.com/Expensify/App/blob/c4d51cfac96f7181511cd4911e5acc93c4813ebd/src/libs/MoneyRequestReportUtils.ts#L122-L130

As a result, ReportScreen displays the loading skeleton indefinitely.

https://github.com/Expensify/App/blob/c4d51cfac96f7181511cd4911e5acc93c4813ebd/src/pages/home/ReportScreen.tsx#L353

https://github.com/Expensify/App/blob/c4d51cfac96f7181511cd4911e5acc93c4813ebd/src/pages/home/ReportScreen.tsx#L991

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

In shouldWaitForTransactions, the report.total condition (added in PR https://github.com/Expensify/App/pull/71190) should be stricter.

Suggested update:

const isStillLoadingData = transactions?.length === 0 && 
    ((!!reportMetadata?.isLoadingInitialReportActions && !reportMetadata.hasOnceLoadedReportActions) 
    || (report?.total !== 0 && report?.transactionCount !== 0));

Also, ensure transactionCount is added to the report:

transactionCount: reportOnyx.transactionCount,

Reference:
https://github.com/Expensify/App/blob/c4d51cfac96f7181511cd4911e5acc93c4813ebd/src/pages/home/ReportScreen.tsx#L285

What alternative solutions did you explore? (Optional)

Removing the report completely

First, we need to get the current transactions of the report using the useTransactionsAndViolationsForReport hook. Next, we compare these current transactions with the transactionIDs parameter passed to the deleteTransactions function:

https://github.com/Expensify/App/blob/466a83d596954a6b3ef5fa7cf1c07aab1429f681/src/hooks/useDeleteTransactions.ts#L52

If the removed transactionIDs fully match the current transactions of the report, it means the user is attempting to remove all transactions from that report. In this case, we will call the deleteAppReport API to fully remove the report and return early to avoid calling the updateSplitTransactions/deleteMoneyRequest API anymore

cretadn22 avatar Dec 17 '25 09:12 cretadn22

@hoangzinh Whoops! This issue is 2 days overdue. Let's get this updated quick!

melvin-bot[bot] avatar Dec 18 '25 23:12 melvin-bot[bot]

@hoangzinh @VictoriaExpensify this issue is now 4 weeks old, please consider:

  • Finding a contributor to fix the bug
  • Closing the issue if BZ has been unable to add the issue to a VIP or Wave project
  • If you have any questions, don't hesitate to start a discussion in #expensify-open-source

Thanks!

melvin-bot[bot] avatar Dec 19 '25 21:12 melvin-bot[bot]

๐Ÿ“ฃ It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? ๐Ÿ’ธ

melvin-bot[bot] avatar Dec 21 '25 16:12 melvin-bot[bot]

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

melvin-bot[bot] avatar Dec 23 '25 00:12 melvin-bot[bot]

Reviewing today

hoangzinh avatar Dec 23 '25 08:12 hoangzinh

@cretadn22 I'm interested in your alternative solution, is it possible to call deleteMoneyRequest after updateSplitTransactions when the split transaction is the last one on the report?

hoangzinh avatar Dec 25 '25 08:12 hoangzinh

is it possible to call deleteMoneyRequest after updateSplitTransactions when the split transaction is the last one on the report?

@hoangzinh That approach is possible, but Iโ€™m a bit concerned it may not be allowed per the documentation, since it involves calling two consecutive APIs for a single user action.

https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/contributingGuides/API.md?plain=1#L5-L6

cretadn22 avatar Dec 25 '25 15:12 cretadn22