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
Expense - "Pay with personal account" instead of "Pay with wallet" is shown #87734
Version Number: 9.3.58-7 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:#84657 Email or phone of affected tester (no customers):dayis32673@nyspring.com Issue reported by: Applause Internal Team Bug source: Exploratory - Significant User Experience Deterioration Device used: Mac 26.2 / Chrome App Component: Money Requests
Action Performed:
Precondition:
User has personal bank account.
User has received two IOU expenses in USD currency from another user.
Go to staging.new.expensify.com
Open IOU report with two expenses in USD currency from another user.
Click Pay dropdown button.
→ Pay with wallet is shown.
Bulk select both expenses.
Click More > Pay.
Expected Result:
"Pay with wallet" option will be shown.
Actual Result:
"Pay with personal account" instead of "Pay with wallet" is shown.
👋 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:
Identify the pull request that introduced this issue and revert it.
Classification: Frontend bug
Causing PR: #85796 - "Add selection mode Submit/Approve/Pay actions for mobile layout." by @Krishna2323 (High confidence)
Note on melvin-bot attribution: The auto-assigned PR #84657 was included in the regression test field of the issue body as the feature being tested, not the causing PR. The actual bug was discovered while testing that duplicate-expense feature.
Recommendation: REVERT
PR #85796 directly introduced the selection-mode Pay button with payment sub-menu (via the new useSelectionModeReportActions hook), and is already flagged as unchecked in the StagingDeployCash. The selection-mode "More > Pay" submenu is showing "Pay with personal account" instead of "Pay with wallet" for IOU reports with an activated wallet. Reverting this PR would remove the selection-mode Submit/Approve/Pay actions and restore the previous behavior.
Assigned: @Krishna2323 (PR author), @situchan (approving reviewer), @puneetlath (approving reviewer)
Labels: No label changes needed. DeployBlockerCash should remain as this is a Frontend bug in Expensify/App.
Detailed Analysis:
Evidence:
The bug affects the "More > Pay" dropdown in bulk selection mode on an IOU report with USD expenses.
Step 3 of the reproduction confirms "Pay with wallet" shows correctly for the single (non-bulk) Pay button, meaning the user has an activated wallet and the base payment logic is correct.
Step 5 shows "Pay with personal account" in the bulk selection "More > Pay" submenu, which is a different code path.
The paymentSubMenuItems built inside useSelectionModeReportActions uses usePaymentOptions to determine payment option text.
Root Cause:
PR #85796 introduced useSelectionModeReportActions, which constructs the payment sub-menu for the selection-mode Pay action. The paymentSubMenuItems are built from paymentButtonOptions returned by usePaymentOptions. The personal payment option text is determined by: hasActivatedWallet ? translate("iou.settleWallet") : translate("iou.settlePersonal"). There is likely a subtle difference in how the hook resolves parameters in the new context versus the original MoneyReportHeader context, causing it to render "Pay with personal account" even when the wallet is activated.
The single-report Pay button (usePaymentOptions.ts:156) and the bulk Pay action (useBulkPayOptions.ts:155-164) use different logic to determine the payment option text.
Single report (usePaymentOptions.ts:122-123): When canUseWallet is true, always shows hasActivatedWallet ? "Pay with wallet" : "Pay with personal account". No bank account list check.
Bulk path (useBulkPayOptions.ts:155-164): Has a two-branch decision:
Branch 1 (line 156): If personalBankAccountList.length > 0 AND canUsePersonalBankAccount → hardcodes "Pay with wallet" (no hasActivatedWallet check)
Branch 2 (line 162): If personalBankAccountList is empty AND canUsePersonalBankAccount → uses paymentMethods[PERSONAL_BANK_ACCOUNT] from SettlementButtonUtils.ts:101, which shows hasActivatedWallet ? "Pay with wallet" : "Pay with personal account"
The bug occurs when:
personalBankAccountList is empty — either bank account data (ONYXKEYS.BANK_ACCOUNT_LIST) hasn't hydrated on the search page, or the account's accountData.type doesn't match CONST.BANK_ACCOUNT.TYPE.PERSONAL
hasActivatedWallet is false — ONYXKEYS.USER_WALLET hasn't hydrated yet on the search page
Search results are stored in ONYXKEYS.COLLECTION.SNAPSHOT (Search.ts:300-306), not in ONYXKEYS.COLLECTION.REPORT. This means wallet and bank account data may not be hydrated at the time the bulk pay options are rendered on the search page, while they are reliably available on the report page.
Note: PR #84657 did NOT change any payment logic — the diff only adds bulk duplication. This bug is likely pre-existing.
What changes do you think we should make in order to solve the problem?
In useBulkPayOptions.ts, make the wallet option logic consistent with usePaymentOptions.ts. When canUseWallet and canUsePersonalBankAccount are both true, the text should always depend on hasActivatedWallet, not on personalBankAccountList.length. Specifically, replace the two-branch logic at lines 155-164 so that the hasActivatedWallet check determines the text regardless of whether personal bank accounts are in the list — matching how usePaymentOptions.ts:122-123 works.
What alternative solutions did you explore?
Alternatively, ensure USER_WALLET and BANK_ACCOUNT_LIST Onyx data are eagerly loaded when the search page mounts (e.g., via OpenApp or a dedicated API call). This would fix the hydration timing issue but is more invasive and doesn't address the fundamental logic inconsistency between the two hooks.
useSearchBulkActions calls useBulkPayOptions with selectedReportID and isCurrencySupportedWallet
useBulkPayOptions loads userWallet and bankAccountList from Onyx
If bankAccountList hasn't hydrated → personalBankAccountList is empty → Branch 1 skipped
If userWallet hasn't hydrated → hasActivatedWallet is false → Branch 2 shows "Pay with personal account"
Next Steps for Contributor+ team: Reply with @MelvinBot implement this to create a draft PR, @MelvinBot <your feedback> to refine this analysis, or explain why you are rejecting Melvin's proposal.
@dylanexpensify@puneetlath When a user has a personal bank account linked but hasn't completed KYC (wallet tier < Gold), should the button say "Pay with wallet" (matching SettlementButton, but misleading since it triggers KYC) or "Pay with personal account" (matching usePaymentOptions, arguably more honest)?
We show Pay with personal account if the user hasn't set up a personal bank account yet, as a prompt to add one and activate their wallet. If they have a personal bank account setup, we show Pay with wallet. The wallet flow isn't really prioritized now at all, but for consistency sake, good with me to update the label used in the bulk selection pay flow here.
Activity
melvin-bot commentedon Apr 13, 2026
You have been assigned to this deploy blocker because you recently merged this PR: #84657
melvin-bot commentedon Apr 13, 2026
💬 A slack conversation has been started in #expensify-open-source
github-actions commentedon Apr 13, 2026
👋 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:
OSBotify commentedon Apr 13, 2026
Investigation Summary
Classification: Frontend bug
Causing PR: #85796 - "Add selection mode Submit/Approve/Pay actions for mobile layout." by @Krishna2323 (High confidence)
Note on melvin-bot attribution: The auto-assigned PR #84657 was included in the regression test field of the issue body as the feature being tested, not the causing PR. The actual bug was discovered while testing that duplicate-expense feature.
Recommendation: REVERT
PR #85796 directly introduced the selection-mode Pay button with payment sub-menu (via the new useSelectionModeReportActions hook), and is already flagged as unchecked in the StagingDeployCash. The selection-mode "More > Pay" submenu is showing "Pay with personal account" instead of "Pay with wallet" for IOU reports with an activated wallet. Reverting this PR would remove the selection-mode Submit/Approve/Pay actions and restore the previous behavior.
Assigned: @Krishna2323 (PR author), @situchan (approving reviewer), @puneetlath (approving reviewer)
Labels: No label changes needed. DeployBlockerCash should remain as this is a Frontend bug in Expensify/App.
Detailed Analysis:
Evidence:
Verification:
Root Cause:
PR #85796 introduced useSelectionModeReportActions, which constructs the payment sub-menu for the selection-mode Pay action. The paymentSubMenuItems are built from paymentButtonOptions returned by usePaymentOptions. The personal payment option text is determined by: hasActivatedWallet ? translate("iou.settleWallet") : translate("iou.settlePersonal"). There is likely a subtle difference in how the hook resolves parameters in the new context versus the original MoneyReportHeader context, causing it to render "Pay with personal account" even when the wallet is activated.
MelvinBot commentedon Apr 13, 2026
Proposal
What is the root cause of that problem?
The single-report Pay button (
usePaymentOptions.ts:156) and the bulk Pay action (useBulkPayOptions.ts:155-164) use different logic to determine the payment option text.Single report (
usePaymentOptions.ts:122-123): WhencanUseWalletis true, always showshasActivatedWallet ? "Pay with wallet" : "Pay with personal account". No bank account list check.Bulk path (
useBulkPayOptions.ts:155-164): Has a two-branch decision:personalBankAccountList.length > 0ANDcanUsePersonalBankAccount→ hardcodes "Pay with wallet" (nohasActivatedWalletcheck)personalBankAccountListis empty ANDcanUsePersonalBankAccount→ usespaymentMethods[PERSONAL_BANK_ACCOUNT]fromSettlementButtonUtils.ts:101, which showshasActivatedWallet ? "Pay with wallet" : "Pay with personal account"The bug occurs when:
personalBankAccountListis empty — either bank account data (ONYXKEYS.BANK_ACCOUNT_LIST) hasn't hydrated on the search page, or the account'saccountData.typedoesn't matchCONST.BANK_ACCOUNT.TYPE.PERSONALhasActivatedWalletis false —ONYXKEYS.USER_WALLEThasn't hydrated yet on the search pageSearch results are stored in
ONYXKEYS.COLLECTION.SNAPSHOT(Search.ts:300-306), not inONYXKEYS.COLLECTION.REPORT. This means wallet and bank account data may not be hydrated at the time the bulk pay options are rendered on the search page, while they are reliably available on the report page.Note: PR #84657 did NOT change any payment logic — the diff only adds bulk duplication. This bug is likely pre-existing.
What changes do you think we should make in order to solve the problem?
In
useBulkPayOptions.ts, make the wallet option logic consistent withusePaymentOptions.ts. WhencanUseWalletandcanUsePersonalBankAccountare both true, the text should always depend onhasActivatedWallet, not onpersonalBankAccountList.length. Specifically, replace the two-branch logic at lines 155-164 so that thehasActivatedWalletcheck determines the text regardless of whether personal bank accounts are in the list — matching howusePaymentOptions.ts:122-123works.What alternative solutions did you explore?
Alternatively, ensure
USER_WALLETandBANK_ACCOUNT_LISTOnyx data are eagerly loaded when the search page mounts (e.g., viaOpenAppor a dedicated API call). This would fix the hydration timing issue but is more invasive and doesn't address the fundamental logic inconsistency between the two hooks.Investigation details
Key files:
useBulkPayOptions.ts:155-164— bulk payment option logic (search page)usePaymentOptions.ts:122-123— single report payment option logicSettlementButtonUtils.ts:100-101— shared payment method definitionsuseSearchBulkActions.ts:321-328— callsuseBulkPayOptionsData flow:
useSearchBulkActionscallsuseBulkPayOptionswithselectedReportIDandisCurrencySupportedWalletuseBulkPayOptionsloadsuserWalletandbankAccountListfrom OnyxbankAccountListhasn't hydrated →personalBankAccountListis empty → Branch 1 skippeduserWallethasn't hydrated →hasActivatedWalletis false → Branch 2 shows "Pay with personal account"Next Steps for Contributor+ team: Reply with
@MelvinBot implement thisto create a draft PR,@MelvinBot <your feedback>to refine this analysis, or explain why you are rejecting Melvin's proposal.32 remaining items
mallenexpensify commentedon Apr 28, 2026
Please comment and tag me if/when payment is due, thx
Krishna2323 commentedon Apr 30, 2026
@dylanexpensify @puneetlath When a user has a personal bank account linked but hasn't completed KYC (wallet tier < Gold), should the button say "Pay with wallet" (matching
SettlementButton, but misleading since it triggers KYC) or "Pay with personal account" (matchingusePaymentOptions, arguably more honest)?puneetlath commentedon Apr 30, 2026
Hmm, what is the functional difference between paying with your wallet or paying with your personal account?
cc @joekaufmanexpensify
joekaufmanexpensify commentedon May 1, 2026
We show
Pay with personal accountif the user hasn't set up a personal bank account yet, as a prompt to add one and activate their wallet. If they have a personal bank account setup, we showPay with wallet. The wallet flow isn't really prioritized now at all, but for consistency sake, good with me to update the label used in the bulk selection pay flow here.melvin-bot commentedon May 5, 2026
@Krishna2323 Eep! 4 days overdue now. Issues have feelings too...
melvin-bot commentedon May 7, 2026
@Krishna2323 6 days overdue. This is scarier than being forced to listen to Vogon poetry!
Krishna2323 commentedon May 8, 2026
@puneetlath @situchan PR is ready for review #89962.
Krishna2323 commentedon May 22, 2026
@puneetlath we can close this issue. The payment for this should be handled under #72502.