[$250] Expense - The “Paid” tag disappears after pay with personal account.
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.75-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: https://test-management.browserstack.com/projects/2219752/test-runs/TR-2349/folder/13176679/41237860/1068908367 Email or phone of affected tester (no customers): [email protected] Issue reported by: Applause Internal Team Bug source: Regression TC Execution Device used: Samsung A16 / Android 15 / Windows 11 / Chrome App Component: Money Requests
Action Performed:
- Open https://staging.new.expensify.com/.
- Create a new account and verify with MC.
- Go to a 1:1 DM with another user.
- Tap on the "+" button and tap on "Pay (User)".
- Type any amount and submit it.
Expected Result:
The “Paid” tag should always be displayed after paying a user.
Actual Result:
The “Paid” tag disappears a few seconds after paying the user.
Workaround:
Unknown
Platforms:
- [x] Android: App
- [ ] Android: mWeb Chrome
- [x] iOS: App
- [ ] iOS: mWeb Safari
- [ ] iOS: mWeb Chrome
- [x] Windows: Chrome
- [ ] MacOS: Chrome / Safari
- [ ] MacOS: Desktop
Screenshots/Videos
https://github.com/user-attachments/assets/6b88944c-59ad-4152-b9d8-52c178cf11c7
Upwork Automation - Do Not Edit
- Upwork Job URL: https://www.upwork.com/jobs/~022001452335480744761
- Upwork Job ID: 2001452335480744761
- Last Price Increase: 2025-12-25
Issue Owner
Current Issue Owner: @shubham1206agra
Triggered auto assignment to @lydiabarclay (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.
Proposal
Please re-state the problem that we are trying to solve in this issue.
The “Paid” tag disappears a few seconds after paying the user.
What is the root cause of that problem?
The status badge disappears because childMoneyRequestCount in action has the value undefined after the API returns data.
https://github.com/Expensify/App/blob/6db192d3ca17bfb95bf0a9058c62e23943ddf9ee/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx#L695
What changes do you think we should make in order to solve the problem?
Instead of relying only on action?.childMoneyRequestCount, we could accurately check from the childReport of the action if transactionCount > 0.
https://github.com/Expensify/App/blob/6db192d3ca17bfb95bf0a9058c62e23943ddf9ee/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx#L695
{!!reportStatus && (!!action?.childMoneyRequestCount || !!getReportOrDraftReport(action?.childReportID)?.transactionCount) && (
What alternative solutions did you explore? (Optional)
N/A
Proposal
Please re-state the problem that we are trying to solve in this issue.
When a user pays another user in a 1:1 DM by tapping the "+" button, selecting "Pay (User)", entering an amount, and submitting, the "Paid" tag appears initially but disappears a few seconds after the payment is completed. The "Paid" tag should always be displayed after paying a user and should persist.
What is the root cause of that problem?
The issue occurs in the MoneyRequestReportPreviewContent component where the reportStatus is computed. The root cause is a timing issue during server response updates:
-
Optimistic Update: When payment is initiated, the optimistic update sets
iouReport.statusNumtoCONST.REPORT.STATUS_NUM.REIMBURSED, which correctly shows the "Paid" tag initially. -
Server Response Gap: When the server response arrives, there's a brief moment where:
- The
iouReport?.statusNummight be temporarily undefined or not yet updated - The
action?.childStatusNummight also be temporarily undefined - This causes
getReportStatusTranslation()to return an empty string
- The
-
Status Computation: The
reportStatusis computed using:stateNum: iouReport?.stateNum ?? action?.childStateNum, statusNum: iouReport?.statusNum ?? action?.childStatusNum,When both values are temporarily undefined during the server response update, the status becomes empty, causing the "Paid" tag to disappear.
-
Existing Check Not Used: The component already has an
iouSettledcheck that correctly identifies when a report is settled by checking bothisSettled(iouReportID)andaction?.childStatusNum === CONST.REPORT.STATUS_NUM.REIMBURSED, but this check is not used in thereportStatuscomputation.
What changes do you think we should make in order to solve the problem?
Modify the reportStatus and reportStatusColorStyle computations in MoneyRequestReportPreviewContent.tsx to check iouSettled first. If the report is settled, ensure the "Paid" status is always shown by using CONST.REPORT.STATUS_NUM.REIMBURSED for the statusNum, even if the values are temporarily missing during server updates.
File: App/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx
Code Changes:
-
Update
reportStatuscomputation (around line 345):
Before:
const reportStatus = useMemo(
() =>
getReportStatusTranslation({
stateNum: iouReport?.stateNum ?? action?.childStateNum,
statusNum: iouReport?.statusNum ?? action?.childStatusNum,
translate,
}),
[action?.childStateNum, action?.childStatusNum, iouReport?.stateNum, iouReport?.statusNum, translate],
);
After:
const reportStatus = useMemo(() => {
// If the report is settled, ensure we show "Paid" status even if statusNum is temporarily missing
// This prevents the "Paid" tag from disappearing during server response updates
if (iouSettled) {
const stateNum = iouReport?.stateNum ?? action?.childStateNum ?? CONST.REPORT.STATE_NUM.APPROVED;
return getReportStatusTranslation({
stateNum,
statusNum: CONST.REPORT.STATUS_NUM.REIMBURSED,
translate,
});
}
return getReportStatusTranslation({
stateNum: iouReport?.stateNum ?? action?.childStateNum,
statusNum: iouReport?.statusNum ?? action?.childStatusNum,
translate,
});
}, [action?.childStateNum, action?.childStatusNum, iouReport?.stateNum, iouReport?.statusNum, iouSettled, translate]);
-
Update
reportStatusColorStylecomputation (around line 355):
Before:
const reportStatusColorStyle = useMemo(
() => getReportStatusColorStyle(theme, iouReport?.stateNum ?? action?.childStateNum, iouReport?.statusNum ?? action?.childStatusNum),
[action?.childStateNum, action?.childStatusNum, iouReport?.stateNum, iouReport?.statusNum, theme],
);
After:
const reportStatusColorStyle = useMemo(() => {
// If the report is settled, ensure we show "Paid" color style even if statusNum is temporarily missing
if (iouSettled) {
const stateNum = iouReport?.stateNum ?? action?.childStateNum ?? CONST.REPORT.STATE_NUM.APPROVED;
return getReportStatusColorStyle(theme, stateNum, CONST.REPORT.STATUS_NUM.REIMBURSED);
}
return getReportStatusColorStyle(theme, iouReport?.stateNum ?? action?.childStateNum, iouReport?.statusNum ?? action?.childStatusNum);
}, [action?.childStateNum, action?.childStatusNum, iouReport?.stateNum, iouReport?.statusNum, iouSettled, theme]);
Why this works:
- The
iouSettledcheck already correctly identifies when a report is settled by checking both the report status and the action's child status - By using this check in the status computation, we ensure the "Paid" tag persists even when individual status values are temporarily undefined during server updates
- This maintains consistency with the existing logic that uses
iouSettledfor other UI elements (like the checkmark animation) - The dependency arrays are updated to include
iouSettledto ensure the memoized values update when the settled state changes
What alternative solutions did you explore? (Optional)
None
Will review asap
Job added to Upwork: https://www.upwork.com/jobs/~022001452335480744761
Triggered auto assignment to Contributor-plus team member for initial proposal review - @shubham1206agra (External)
@lydiabarclay Can you get someone here to answer the following question?
Why does
childMoneyRequestCountgo to undefined inSendMoneyElsewherecommand?
@shubham1206agra Whoops! This issue is 2 days overdue. Let's get this updated quick!
📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸
@shubham1206agra @lydiabarclay 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!
@shubham1206agra Eep! 4 days overdue now. Issues have feelings too...