Skip to content

[Due for payment 2026-08-27] Expense -Deleted split remains in Self DM with infinite loading after being deleted on Spend #97413

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.46-0
Reproducible in staging?: Yes
Reproducible in production?: N/A - new feature, doesn't exist in prod
If this was caught during regression testing, add the test name, ID and link from BrowserStack: #92055
Email or phone of affected tester (no customers): ibellicotest+2766@gmail.com
Issue reported by: Applause Internal Team
Bug source: Exploratory - Significant User Experience Deterioration
Device used: Motorola MotoG60 / Android 12 (Hybrid app) - Windows 11 / Chrome
App Component: Money Requests

Action Performed:

Prerequisite: Account has Self DM.

  1. Open the staging.new.expensify.com website.
  2. Navigate to Self DM.
  3. Create a manual expense.
  4. Navigate to "Spend" > "Expenses"
  5. Select the just created expense.
  6. Click on dropdown menu > "Split" > Save splits.
  7. Select one of the splits and delete it.
  8. Select the remaining split and delete it too.
  9. Navigate to Self DM.
  10. Note that an expense preview with infinite loading is visible.
  11. Open the expense.
  12. Note that "It´s not here" page opens.
  13. Return to chat and delete expense.
  14. Note that now, expense disappears.

Expected Result:

Split deleted while on "Spend", should automatically disappear from chat too.

Actual Result:

Split deleted while on "Spend", remains in Self DM showing infinite loading on preview and leads to "It´s not here" page.

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

Bug7221341_1785363236415.Deleted_Split_1.mp4

View all open jobs on GitHub

Applause Internal Information
Exported by: Vincenzo Godoy
Bug ID: 7221341

Issue OwnerCurrent Issue Owner: @ZhenjaHorbach

Activity

  1. added
    DeployBlockerCashThis issue or pull request should block deployment
    BugSomething is broken. Auto assigns a BugZero manager.
    on Jul 30, 2026
  2. applause-bot commented on Jul 30, 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/a978ba3b6cb2a49094d9f5675bec46914466e0a67ca29b3c3a58b1ceab0021cb

  3. melvin-bot commented on Jul 30, 2026

    @melvin-bot

    You have been assigned to this deploy blocker because you recently merged this PR: #92055

  4. melvin-bot commented on Jul 30, 2026

    @melvin-bot

    @lakchote @dmkt9 you have been assigned to this deploy blocker because you reviewed the offending PR: #92055

  5. melvin-bot commented on Jul 30, 2026

    @melvin-bot

    @ZhenjaHorbach you have been assigned to this deploy blocker because you authored the offending PR: #92055

  6. melvin-bot commented on Jul 30, 2026

    @melvin-bot

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

  7. github-actions commented on Jul 30, 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.
  8. MelvinBot commented on Jul 30, 2026

    @MelvinBot
    Contributor

    🔍 Investigation Summary

    Classification: Frontend bug
    Causing PR: #92055 - "Fix bugs for selfDM splits feature" by @ZhenjaHorbach (High confidence)
    Related Issues: N/A

    Recommendation: ROLL FORWARD (targeted fix)

    The orphaned Self DM preview is pure client-side optimistic-Onyx cleanup logic that PR #92055 restructured; reverting is unsafe because that PR bundles fixes for 8 separate self-DM-split issues (#91874, #91876, #91879, #91907, #91913, #91917, #91918, #91920), so a revert would reintroduce all of them. A targeted fix in useDeleteTransactions is smaller and lower-risk.

    Assigned: @ZhenjaHorbach (PR author), @lakchote and @dmkt9 (approving reviewers) — already assigned by melvin-bot
    Labels: No change. DeployBlockerCash is kept (App-side fix, and the issue is a new feature that is N/A in production). DeployBlocker was not present.

    📋 Detailed Analysis

    Evidence

    • The bug is N/A in production and only reproduces on staging — this is a brand-new feature path (splitting a Self DM expense, then deleting the split(s) from the "Spend" > Expenses / Search view). There is no server error involved; the visible symptom is an optimistic Onyx report preview that is never cleaned up (infinite-loading preview → "It's not here"), which is entirely front-end state.
    • PR Fix bugs for selfDM splits feature #92055 is the offending PR flagged by melvin-bot and is also the link given for "caught during regression testing." Confirming what it changed: it heavily restructured exactly the two files that own this flow:
      • src/hooks/useDeleteTransactions.ts — the delete-from-Search classification logic (added isMovedExpenseSplitChild, TransactionWithAction, changed how split children are grouped by original transaction).
      • src/libs/actions/IOU/SplitTransactionUpdate.ts — the reverse-split / report-action cleanup logic (firstIOU → iouActionsToCleanUp loop that marks the original IOU action DELETE, the isLastTransactionInReport report teardown, and the snapshot rescaling).
    • Because the affected code is the delete + Self-DM-cleanup path that this PR rewrote, and the feature does not exist in prod, this PR is the source of the regression.

    Verification

    • Affected files (confirmed present in the merged code at f704af6):
      • src/hooks/useDeleteTransactions.ts
      • src/libs/actions/IOU/SplitTransactionUpdate.ts
    • Confirmed PR Fix bugs for selfDM splits feature #92055 modifies both (via gh pr view 92055 --json files). Merge commit 2f02df8381ffcea859f6546963ac6ef1d2e12c21.
    • Confirmed the manual-expense repro does not hit the per-diem "redirect to split-edit" branch: shouldRedirectDeleteToSplitExpenseEdit requires isPerDiemRequest, so a manual split falls through to the normal delete path below.
    • Confirmed on staging (isProduction === false) getChildTransactions includes the unreported Self-DM split children (the isProduction guard that would exclude them is skipped), so the delete path treats them as split children.

    Root Cause

    When splits are deleted from the "Spend"/Search view, deleteTransactions groups the Self-DM split children under their originalTransactionID. In the per-original loop, when every remaining child of an original is being removed, the code takes this early branch:

    src/hooks/useDeleteTransactions.ts#L252-L255

    if (childTransactions.length === 0) {
        nonSplitTransactions.push(...splitTransactionsByOriginalTransactionID[transactionID]);
        continue;
    }

    Those children are then deleted one-by-one via the plain deleteMoneyRequest loop, which only tears down each split's own transaction + transaction thread (action.childReportID).

    Crucially, this branch bypasses updateSplitTransactions — the only code that knows how to reconcile the original (container) transaction. When a Self-DM expense is split, the original transaction is moved into the hidden SPLIT_REPORT_ID container and its Self-DM IOU/report-preview action is what the user still sees in chat. The container/preview is only ever cleaned up (marked DELETE, report torn down) inside updateSplitTransactions via the iouActionsToCleanUp and isLastTransactionInReport logic. Because deleting the last child skips that function entirely, the original container transaction and its Self DM report preview are left orphaned: the preview references a transaction that no longer resolves, producing the infinite loading spinner and the "It's not here" page. Manually deleting the leftover preview afterward is what finally clears it (matching the reported workaround at step 13-14).

    In short: the childTransactions.length === 0 shortcut deletes the leaf split transactions but never restores-and-deletes (or directly cleans up) the original Self-DM split container + its report-preview action.

    Suggested fix direction (for the assignees)

    When childTransactions.length === 0 for an original that is a Self-DM split container, route the deletion through the split reconciliation path (updateSplitTransactions / reverse-split teardown) so the original container transaction is removed and its Self-DM report-preview action is marked DELETE, instead of falling back to per-child deleteMoneyRequest. This mirrors the cleanup already applied when at least one child survives.

  9. 5 remaining items

  10. melvin-bot commented on Aug 19, 2026

    @melvin-bot

    ⚠️ Looks like this issue was linked to a Deploy Blocker here

    If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results.

    If a regression has occurred and you are the assigned CM follow the instructions here.

    If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future.

  11. melvin-bot commented on Aug 19, 2026

    @melvin-bot

    ⚠️ Looks like this issue was linked to a Deploy Blocker here

    If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results.

    If a regression has occurred and you are the assigned CM follow the instructions here.

    If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future.

  12. melvin-bot commented on Aug 20, 2026

    @melvin-bot

    @ZhenjaHorbach / @dmkt9

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.4.56-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-08-27. 🎊

    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]. If no checklist is needed for this issue, you can click: [no checklist button]

  13. changed the title [-]Expense -Deleted split remains in Self DM with infinite loading after being deleted on Spend[/-] [+][Due for payment 2026-08-27] Expense -Deleted split remains in Self DM with infinite loading after being deleted on Spend[/+] on Aug 20, 2026
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.DailyKSv2Engineering

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions