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-11-03] [$175] Spend - Deleted card expenses display with no owner (From column) #103480
Version Number: 9.5.3-4 Reproducible in staging?: Y Reproducible in production?: Y If this was caught during regression testing, add the test name, ID and link from BrowserStack: Email or phone of affected tester (no customers): N/A Logs: N/A Expensify/Expensify Issue URL: N/A Issue reported by:@flaviadefaria Slack conversation (hyperlinked to channel name): N/A
Action Performed:
Setup
Log in as policy admin
Invite a member
Workspace settings > Company cards > Add cards
Proceed with United States.
Proceed with Direct feed.
Select Other and then Next. This opens the Plaid UI.
Tap Continue as guest.
Select any bank. I typically do US Bank.
Enter the Plaid test credentials:
username: user_good
password: pass_good
If prompted for a security code, enter: credential_good.
Select the Plaid credit card ending x3333
Follow the remaining steps to connect the card(s) in Plaid.
In the card feed settings, set Allow deleting transactions to disabled
Assign the card to the member
Select From the beginning to import historical transactions.
Steps
As the admin, select one of the card expenses in the Spend page
Verify the delete option is available
Delete the card expense
View deleted expenses (Filters > Status > Deleted)
Add the From column if it isn't already present
Expected Result:
The From column displays the owner of the card transaction
Actual Result:
The From column is empty. After undeleting, the column displays correctly
Workaround:
Can the user still use Expensify without this being fixed? Have you informed them of the workaround?
Platforms:
Select the officially supported platforms where the issue was reproduced:
Root Cause: A deleted expense has no parent report in Search. Its reportID is the trash ID -1. The App reads the From value from only two places: the expense's IOU report action, or the parent report's owner (SearchUIUtils.ts:1886-1887). The report lookup always fails for -1. The Search response for deleted expenses doesn't include the IOU action, so the App falls back to empty personal details, and the cell renders blank. After you undelete, the real report returns and its ownerAccountID fills From.
This isn't specific to card expenses. In a web test, a deleted cash expense also showed an empty From cell.
Recommended Fix: The fix needs a backend change, outside the App repo. Search needs to return the owner for deleted expenses. It can return either the IOU report action (with IOUTransactionID) or an owner account ID on the transaction, plus that owner's personal details. Please escalate to an internal engineer with backend access. Once the backend sends an owner field, the App can add it as a fallback in both From paths (SearchUIUtils.ts:1886 and SearchUIUtils.ts:2936).
Investigation details
How From is resolved (App, at 5d3a894)
The App looks up the report by the transaction's reportID (SearchUIUtils.ts:1852). For deleted expenses, reportID is CONST.REPORT.TRASH_REPORT_ID ('-1'), so report is undefined.
fromAccountID = reportAction?.actorAccountID ?? report?.ownerAccountID resolves to undefined, so from becomes emptyPersonalDetails (account ID 0). UserInfoCell returns null for account ID 0, so the cell renders blank instead of showing "Hidden".
The grouped path uses only the IOU action, with no report fallback (SearchUIUtils.ts:2936).
An existing comment already notes that Search doesn't return the IOU action for deleted items (SearchUIUtils.ts:2532-2533).
The Search transaction data has no owner or account ID field the App could use instead.
Web test (cash expense)
I created a manual expense, submitted it to a workspace, and deleted it. Then I opened Filters > Status > Deleted and grouped by From to show the From column. The group header showed the submitter, but the expense's own From cell was empty. Date, Status, Merchant, Category, and Amount all showed normally.
Alternatives considered
Card-specific behavior: The App handles card and cash expenses the same way here, and the cash test reproduced the bug.
App-only card fallback: The App could use cardList[transaction.cardID].accountID for card expenses. This would leave cash expenses broken. It also depends on the admin's cardList holding members' cards, which I didn't verify.
Missing personal details rather than a missing action: This is unlikely. In the cash test, the owner was the signed-in user, whose details are always loaded.
Not verified: I didn't check the backend Search code or capture a raw Search response. "Search omits the IOU action for deleted expenses" comes from App behavior and the existing code comment.
Next Steps: Escalate the backend change to an internal engineer, or reply with @MelvinBot <your feedback> to refine this analysis.
changed the title [-]Spend - Deleted card expenses display with no owner (From column)[/-][+][$175] Spend - Deleted card expenses display with no owner (From column)[/+]on Oct 8, 2026
Please re-state the problem that we are trying to solve in this issue.
In Workspace > Spend (and Search), when viewing deleted company card expenses (Filters > Status > Deleted), the From column displays empty rather than showing the owner / cardholder of the transaction. Once undeleted, the column displays the owner correctly.
Its reportID becomes CONST.REPORT.TRASH_REPORT_ID ('-1'), so report lookup returns undefined.
The Search snapshot does not include the IOU report actions for deleted transactions, so reportAction is also undefined.
Consequently, fromAccountID evaluates to undefined, resolving from to emptyPersonalDetails (account ID 0), which causes UserInfoCell to render blank.
However, the deleted transaction still retains its transactionItem.cardID.
Furthermore, cardList (which maps each company card in the workspace to its assigned cardholder accountID) is already passed to getSections at SearchUIUtils.ts:3680 from useSearchSections.ts:65. But getSections currently drops cardList and does not forward it to getTransactionsSections (SearchUIUtils.ts:3747) or getTransactionsSectionsGroupedBy.
What changes do you think we should make in order to solve the problem?
In src/libs/SearchUIUtils.ts, update GetTransactionSectionsParams and GetTransactionsSectionsGroupedByParams to accept cardList and onyxPersonalDetailsList:
In getSections (SearchUIUtils.ts:3747), forward cardList and onyxPersonalDetailsList into getTransactionsSections and getTransactionsSectionsGroupedBy:
In getTransactionsSections (SearchUIUtils.ts:1886-1887), fall back to the card's assigned accountID for card transactions, and fallback to onyxPersonalDetailsList if personalDetailsMap does not contain the member:
What alternative solutions did you explore? (Optional)
Backend modification: Modifying the Search backend endpoint to synthesize an IOU action or include ownerAccountID on deleted transactions. This requires internal backend access and delays the fix. Since the client already has the workspace's assigned cards and cardholders in cardList via Onyx, forwarding cardList to getTransactionsSections completely and cleanly solves this on the client side with zero backend dependencies.
Please re-state the problem that we are trying to solve in this issue.
In Workspace > Spend (and Search), when viewing deleted company card expenses (Filters > Status > Deleted), the From column is empty instead of displaying the cardholder/owner of the transaction. Once undeleted, the owner is displayed properly.
What is the root cause of that problem?
In src/libs/SearchUIUtils.ts:1887-1888 (getTransactionsSections):
Its reportID becomes CONST.REPORT.TRASH_REPORT_ID ('-1').
There is no parent report for '-1' in data, so report resolves to undefined.
The Search results snapshot does not include money request report actions for deleted transactions, so reportAction is also undefined.
Therefore, fromAccountID evaluates to undefined, and from defaults to emptyPersonalDetails, rendering a blank formattedFrom cell in the table.
Although the deleted transaction no longer has an active report or report action, it still retains its transactionItem.cardID. useSearchSections.ts already retrieves both cardList (personalAndWorkspaceCards) and nonPersonalAndWorkspaceCardList (nonPersonalAndWorkspaceCards) from Onyx and forwards them to getSections. However, getSections currently drops cardList, nonPersonalAndWorkspaceCardList, and onyxPersonalDetailsList instead of passing them into getTransactionsSections (and getReportSections).
What changes do you think we should make in order to solve the problem?
1. Update GetTransactionSectionsParams in src/libs/SearchUIUtils.ts
Add cardList, nonPersonalAndWorkspaceCardList, and onyxPersonalDetailsList to GetTransactionSectionsParams and GetReportSectionsParams:
3. Add cardholder fallback in getTransactionsSections (SearchUIUtils.ts:1887-1888)
If reportAction?.actorAccountID and report?.ownerAccountID are undefined, fall back to the assigned card's accountID, and look up details in personalDetailsMap with fallback to onyxPersonalDetailsList:
What specific scenarios should we cover in automated tests?
In tests/unit/SearchUIUtilsTest.ts:
Deleted Company Card Transaction:
Create a deleted transaction (reportID: '-1', cardID: '123') without a report or report action.
Provide cardList with card '123' assigned to accountID: 456.
Verify getTransactionsSections sets from.accountID to 456 and correctly populates formattedFrom.
Undeleted Transaction Precedence:
Verify that for an active transaction with a valid reportAction or report, reportAction.actorAccountID / report.ownerAccountID takes precedence over card.accountID.
Non-Personal / Workspace Card Fallback:
Verify that when the card is in nonPersonalAndWorkspaceCardList, from resolves to the cardholder's details correctly.
@flaviadefaria@arosiclair The issue marks the platform Web only. Do we want to show From on the mobile apps too. But unlike the Wide table, the From is hidden in all deleted expenses (not just card expense).
@flaviadefaria@arosiclair The issue marks the platform Web only. Do we want to show From on the mobile apps too.
Yes, we should make the change also on mobile.
But unlike the Wide table, the From is hidden in all deleted expenses (not just card expense).
I'm not 100% sure that I understood this comment. Normally when viewing expenses on mobile the profile photo/icon and their name display the merchant name. I'd expect us to use this same pattern in the Delete filter for mobile. Let me know if this makes sense or if you have any questions.
Deleted expenses now show From only when the App can still tell who they belonged to, which is card expenses. Deleting an expense removes its report, so Search no longer has the submitter. A card expense can still be matched to the cardholder, and that person is shown as From on web and mobile. Cash, distance, and other non-card expenses have nothing left to look up, so From stays blank until Search returns the owner.
That’s fine, since admins can only delete other users’ credit card expenses. And the most important thing is that they can easily identify which expenses belonged to those users.
changed the title [-][$175] Spend - Deleted card expenses display with no owner (From column)[/-][+][Due for payment 2026-11-03] [$175] Spend - Deleted card expenses display with no owner (From column)[/+]on Oct 27, 2026
The solution for this issue has been 🚀 deployed to production 🚀 in version 9.5.23-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-11-03. 🎊
The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the Contributor+ 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]
Activity
MelvinBot commentedon Oct 8, 2026
Issue Analysis
Root Cause: A deleted expense has no parent report in Search. Its
reportIDis the trash ID-1. The App reads the From value from only two places: the expense's IOU report action, or the parent report's owner (SearchUIUtils.ts:1886-1887). The report lookup always fails for-1. The Search response for deleted expenses doesn't include the IOU action, so the App falls back to empty personal details, and the cell renders blank. After you undelete, the real report returns and itsownerAccountIDfills From.This isn't specific to card expenses. In a web test, a deleted cash expense also showed an empty From cell.
Recommended Fix: The fix needs a backend change, outside the App repo. Search needs to return the owner for deleted expenses. It can return either the IOU report action (with
IOUTransactionID) or an owner account ID on the transaction, plus that owner's personal details. Please escalate to an internal engineer with backend access. Once the backend sends an owner field, the App can add it as a fallback in both From paths (SearchUIUtils.ts:1886andSearchUIUtils.ts:2936).Investigation details
How From is resolved (App, at
5d3a894)reportID(SearchUIUtils.ts:1852). For deleted expenses,reportIDisCONST.REPORT.TRASH_REPORT_ID('-1'), soreportis undefined.SearchUIUtils.ts:1873). That map is filled only from report actions present in the Search snapshot (SearchUIUtils.ts:1509-1514).fromAccountID = reportAction?.actorAccountID ?? report?.ownerAccountIDresolves to undefined, sofrombecomesemptyPersonalDetails(account ID 0).UserInfoCellreturnsnullfor account ID 0, so the cell renders blank instead of showing "Hidden".SearchUIUtils.ts:2936).SearchUIUtils.ts:2532-2533).Web test (cash expense)
I created a manual expense, submitted it to a workspace, and deleted it. Then I opened Filters > Status > Deleted and grouped by From to show the From column. The group header showed the submitter, but the expense's own From cell was empty. Date, Status, Merchant, Category, and Amount all showed normally.
Alternatives considered
cardList[transaction.cardID].accountIDfor card expenses. This would leave cash expenses broken. It also depends on the admin'scardListholding members' cards, which I didn't verify.Not verified: I didn't check the backend Search code or capture a raw Search response. "Search omits the IOU action for deleted expenses" comes from App behavior and the existing code comment.
Next Steps: Escalate the backend change to an internal engineer, or reply with
@MelvinBot <your feedback>to refine this analysis.view run · view recording
melvin-bot commentedon Oct 8, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @mananjadhav (
External)[-]Spend - Deleted card expenses display with no owner (From column)[/-][+][$175] Spend - Deleted card expenses display with no owner (From column)[/+]melvin-bot commentedon Oct 8, 2026
Job added to Upwork: https://www.upwork.com/jobs/~022108208732373682427
yuvrajangadsingh commentedon Oct 8, 2026
withdrawing this, it went up before the issue had the
Help Wantedlabel. will come back if the label is added.strzj1317 commentedon Oct 8, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
In Workspace > Spend (and Search), when viewing deleted company card expenses (Filters > Status > Deleted), the From column displays empty rather than showing the owner / cardholder of the transaction. Once undeleted, the column displays the owner correctly.
What is the root cause of that problem?
In
src/libs/SearchUIUtils.ts:1886-1887,getTransactionsSectionsresolves thefrompersonal details using:And similarly in
getTransactionsSectionsGroupedBy(SearchUIUtils.ts:2936):When an expense is deleted:
reportIDbecomesCONST.REPORT.TRASH_REPORT_ID('-1'), soreportlookup returnsundefined.reportActionis alsoundefined.fromAccountIDevaluates toundefined, resolvingfromtoemptyPersonalDetails(account ID 0), which causesUserInfoCellto render blank.However, the deleted transaction still retains its
transactionItem.cardID.Furthermore,
cardList(which maps each company card in the workspace to its assigned cardholderaccountID) is already passed togetSectionsatSearchUIUtils.ts:3680fromuseSearchSections.ts:65. ButgetSectionscurrently dropscardListand does not forward it togetTransactionsSections(SearchUIUtils.ts:3747) orgetTransactionsSectionsGroupedBy.What changes do you think we should make in order to solve the problem?
src/libs/SearchUIUtils.ts, updateGetTransactionSectionsParamsandGetTransactionsSectionsGroupedByParamsto acceptcardListandonyxPersonalDetailsList:getSections(SearchUIUtils.ts:3747), forwardcardListandonyxPersonalDetailsListintogetTransactionsSectionsandgetTransactionsSectionsGroupedBy:getTransactionsSections(SearchUIUtils.ts:1886-1887), fall back to the card's assignedaccountIDfor card transactions, and fallback toonyxPersonalDetailsListifpersonalDetailsMapdoes not contain the member:getTransactionsSectionsGroupedBy(SearchUIUtils.ts:2936), apply the same fallback:What alternative solutions did you explore? (Optional)
ownerAccountIDon deleted transactions. This requires internal backend access and delays the fix. Since the client already has the workspace's assigned cards and cardholders incardListvia Onyx, forwardingcardListtogetTransactionsSectionscompletely and cleanly solves this on the client side with zero backend dependencies.flaviadefaria commentedon Oct 9, 2026
@mananjadhav thoughts on these proposals?
ashusatyarthi-wq commentedon Oct 9, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
In Workspace > Spend (and Search), when viewing deleted company card expenses (Filters > Status > Deleted), the From column is empty instead of displaying the cardholder/owner of the transaction. Once undeleted, the owner is displayed properly.
What is the root cause of that problem?
In
src/libs/SearchUIUtils.ts:1887-1888(getTransactionsSections):And similarly in
getReportSections(SearchUIUtils.ts:2936):When a company card transaction is deleted:
reportIDbecomesCONST.REPORT.TRASH_REPORT_ID('-1').'-1'indata, soreportresolves toundefined.reportActionis alsoundefined.fromAccountIDevaluates toundefined, andfromdefaults toemptyPersonalDetails, rendering a blankformattedFromcell in the table.Although the deleted transaction no longer has an active report or report action, it still retains its
transactionItem.cardID.useSearchSections.tsalready retrieves bothcardList(personalAndWorkspaceCards) andnonPersonalAndWorkspaceCardList(nonPersonalAndWorkspaceCards) from Onyx and forwards them togetSections. However,getSectionscurrently dropscardList,nonPersonalAndWorkspaceCardList, andonyxPersonalDetailsListinstead of passing them intogetTransactionsSections(andgetReportSections).What changes do you think we should make in order to solve the problem?
1. Update
GetTransactionSectionsParamsinsrc/libs/SearchUIUtils.tsAdd
cardList,nonPersonalAndWorkspaceCardList, andonyxPersonalDetailsListtoGetTransactionSectionsParamsandGetReportSectionsParams:2. Forward card lists and personal details in
getSections(SearchUIUtils.ts:3788)In
getSections, forwardcardList,nonPersonalAndWorkspaceCardList, andonyxPersonalDetailsListtogetTransactionsSectionsandgetReportSections:3. Add cardholder fallback in
getTransactionsSections(SearchUIUtils.ts:1887-1888)If
reportAction?.actorAccountIDandreport?.ownerAccountIDare undefined, fall back to the assigned card'saccountID, and look up details inpersonalDetailsMapwith fallback toonyxPersonalDetailsList:4. Add cardholder fallback in
getReportSections(SearchUIUtils.ts:2936)Apply the same cardholder fallback for individual transaction rows inside report groups:
What specific scenarios should we cover in automated tests?
In
tests/unit/SearchUIUtilsTest.ts:reportID: '-1',cardID: '123') without a report or report action.cardListwith card'123'assigned toaccountID: 456.getTransactionsSectionssetsfrom.accountIDto456and correctly populatesformattedFrom.reportActionorreport,reportAction.actorAccountID/report.ownerAccountIDtakes precedence overcard.accountID.nonPersonalAndWorkspaceCardList,fromresolves to the cardholder's details correctly.ashusatyarthi-wq commentedon Oct 9, 2026
Contributor details
Your Expensify account email: ashusatyarthi@gmail.com
Upwork Profile Link: https://www.upwork.com/freelancers/~010e53044b5828fe60
19 remaining items
mananjadhav commentedon Oct 13, 2026
Reviewing the PR.
mananjadhav commentedon Oct 14, 2026
@flaviadefaria @arosiclair The issue marks the platform Web only. Do we want to show
Fromon the mobile apps too. But unlike the Wide table, the From is hidden in all deleted expenses (not just card expense).flaviadefaria commentedon Oct 15, 2026
Yes, we should make the change also on mobile.
I'm not 100% sure that I understood this comment. Normally when viewing expenses on mobile the profile photo/icon and their name display the merchant name. I'd expect us to use this same pattern in the
Deletefilter for mobile. Let me know if this makes sense or if you have any questions.mananjadhav commentedon Oct 15, 2026
@flaviadefaria Just to clarify that we want to show
Fromin all the deleted expenses? (which currently it's not shown). I'll get it fixed.mananjadhav commentedon Oct 15, 2026
Deleted expenses now show
Fromonly when the App can still tell who they belonged to, which is card expenses. Deleting an expense removes its report, so Search no longer has the submitter. A card expense can still be matched to the cardholder, and that person is shown asFromon web and mobile. Cash, distance, and other non-card expenses have nothing left to look up, soFromstays blank until Search returns the owner.ios-delete-exp-from-user.mov
flaviadefaria commentedon Oct 19, 2026
That’s fine, since admins can only delete other users’ credit card expenses. And the most important thing is that they can easily identify which expenses belonged to those users.
mananjadhav commentedon Oct 23, 2026
The PR is reviewed. @arosiclair All yours.
[-][$175] Spend - Deleted card expenses display with no owner (From column)[/-][+][Due for payment 2026-11-03] [$175] Spend - Deleted card expenses display with no owner (From column)[/+]melvin-bot commentedon Oct 27, 2026
@mananjadhav
The solution for this issue has been 🚀 deployed to production 🚀 in version 9.5.23-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-11-03. 🎊
The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the Contributor+ 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]