Repository navigation
Description
Version Number: Not provided.
Reproducible in staging?: Yes, confirmed by dukenv0307 in the source discussion.
Reproducible in production?: Yes, confirmed in the same discussion.
If this was caught during regression testing, add the test name, ID and link from BrowserStack: Not provided.
Email or phone of affected tester (no customers): Not provided.
Logs: Not provided.
Expensify/Expensify Issue URL: Not provided.
Issue reported by: bernhardoj; also confirmed by dukenv0307.
Slack conversation: Not provided; reported on GitHub.
Action Performed:
Precondition: You are a workspace admin, Payments is enabled, and a business bank account is connected to the workspace.
- Open the workspace in New Expensify and go to Workflows > Payments.
- Turn Payments off. Confirm the warning if one appears.
- Turn Payments back on without refreshing the page or reconnecting the bank account.
- Observe the bank account shown in Payments.
- Refresh the page and observe the bank account again.
Expected Result:
Disabling Payments removes the workspace's bank-account connection from the UI without requiring a refresh. Re-enabling Payments should not display the previous account as connected until you relink it.
The bank account should remain available in your Expensify account; this concerns its connection to the workspace, not deletion of the account.
Actual Result:
After Payments is turned off and back on, the previous bank account still appears connected. It disappears after a refresh.
In the reviewer's report, policy.achAccount is undefined, but bankAccountList still links the bank account to the workspace. This is a reported observation, not a newly verified root cause.
Workaround:
Refresh the page to clear the stale connected-account display. dukenv0307 confirmed this workaround and reproduction on staging/production. No independent reproduction was run when filing this issue.
Platforms:
The report concerns New Expensify. The exact browser and operating system were not provided.
- Android: App
- Android: mWeb Chrome
- iOS: App
- iOS: mWeb Safari
- iOS: mWeb Chrome
- Windows: Chrome
- MacOS: Chrome / Safari
Screenshots/Videos
Reviewer's recording:
https://github.com/user-attachments/assets/c3ff924f-cca4-4f4c-ad51-5dfb941b8bad
Earlier confirmation and recording:
#105333 (comment)
Related context
Filed separately at the request of dukenv0307, outside the scope of Warn admins before turning off Payments when bank account countries or a business bank account are set up.
Potentially related: Clicking the bank account opens “Log into your bank” after toggling Payments off and on. That issue tracks the destination after clicking the stale account; this report tracks the stale connection display and refresh workaround.
Upwork Automation - Do Not Edit
- Upwork Job URL: https://www.upwork.com/jobs/~022118094098919176486
- Upwork Job ID: 2118094098919176486
- Last Price Increase: 2026-11-04
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsCRITICAL
Activity
Hazem20wosis commentedon Nov 4, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue
Payments - When disabling payments on a workspace and then re-enabling them, the previously connected bank account still displays as connected in the UI until the application is refreshed.
What is the root cause of that problem?
In
WorkflowsPaymentsTab.tsx:When payments are turned off via the toggle,
setWorkspaceReimbursementinsrc/libs/actions/Policy/Policy.tssetsreimbursementChoice: CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO, clears the policy'sachAccount, and sendsbankAccountID: 0to the backend.However:
setWorkspaceReimbursementclearspolicy.achAccount, but it does not clearadditionalData.policyIDon the bank account in Onyx'sbankAccountList.getReimbursementChoice(policy) === REIMBURSEMENT_NO, soshouldShowBankAccountevaluates tofalse(hidden).policy.achAccountis cleared/empty. However,bankAccountConnectedToWorkspacelooks solely atbankAccount?.accountData?.additionalData?.policyID === policy?.idin Onyx'sbankAccountList. Because the stalepolicyIDreference remains cached in Onyx,bankAccountConnectedToWorkspaceevaluates to truthy!shouldShowBankAccountimmediately evaluates totrue, and the previously connected bank account unexpectedly reappears on screen until a full refresh forces the client to fetch fresh backend data.What changes do you think we should make in order to solve the problem?
Approach 1 (Comprehensive & Clean Component Safeguard - Recommended):
In
src/pages/workspace/workflows/tabs/WorkflowsPaymentsTab.tsx:A bank account should only be considered connected to the workspace if the policy actually has a configured or pending setup referencing it, rather than blindly trusting stale
additionalData.policyIDwhenpolicy.achAccountis empty/cleared:Or alternatively, cross-verify that the connected bank account matches the policy's
achAccount:This cleanly eliminates the phantom display across all re-enable flows without risking complex nested array mutations or rollback corruptions on global Onyx keys.
Approach 2 (Action-side Onyx Sync in
Policy.ts):In
src/libs/actions/Policy/Policy.ts, insidesetWorkspaceReimbursement:When disabling payments (
reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO):If
oldBankAccountIDexists inbankAccountList, include an optimistic update that removespolicyIDfromaccountData.policyIDsand setsaccountData.additionalData.policyIDtonull:And add corresponding rollbacks in
failureData.Screenshots/Videos
Reproducible Video Evidence & Demonstration
e.mp4
What alternative solutions did you consider?
Clearing
bankAccountListcache completely, but that is overly aggressive as other workspaces or personal payment methods rely onbankAccountList. Approach 1 is the safest and most surgical solution with zero risk of regressions.Contributor details
Your Expensify account email: hazemhazemahmedsalem@gmail.com
Upwork Profile Link: https://www.upwork.com/freelancers/~017a671f901fafe3a1
melvin-bot commentedon Nov 4, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
melvin-bot commentedon Nov 4, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
trjExpensify commentedon Nov 4, 2026
CC: @joekaufmanexpensify @mountiny for vis
melvin-bot commentedon Nov 4, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @FitseTLT (
External)[-]Payments - Previously connected bank account remains visible after disabling and re-enabling Payments until refresh[/-][+][$175] Payments - Previously connected bank account remains visible after disabling and re-enabling Payments until refresh[/+]melvin-bot commentedon Nov 4, 2026
Job added to Upwork: https://www.upwork.com/jobs/~022118094098919176486
mountiny commentedon Nov 4, 2026
Added as critical
Enes2553 commentedon Nov 5, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
When a workspace has a connected business bank account and an admin disables Payments and then re-enables Payments on
Workspace > Workflows, the previously connected bank account immediately reappears as connected until the app is refreshed.What is the root cause of that problem?
In
src/pages/workspace/workflows/tabs/WorkflowsPaymentsTab.tsx:144-160, the connected bank account UI is driven by two Onyx sources:When toggling Payments off (
reimbursementChoice = CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO),setWorkspaceReimbursementinsrc/libs/actions/Policy/Policy.ts:1480-1654sendsbankAccountID: 0to the backend (line 1650), but fails to clear the connected bank account in Onyx:policy.achAccountis overwritten with the old bank account instead ofnull(Policy.ts:1517):optimisticDatamergesachAccount: {reimburser: reimburserEmail, bankAccountID, accountNumber, addressName, bankName, state}into${ONYXKEYS.COLLECTION.POLICY}${policyID}even whenshouldClearBankAccountID(reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO) istrue.ONYXKEYS.BANK_ACCOUNT_LISTretains the workspace'spolicyID(WorkflowsPaymentsTab.tsx:324&Policy.ts:1498-1549):WorkflowsPaymentsTab.tsx:324does not passbankAccountListtosetWorkspaceReimbursement.oldBankAccountIDinPolicy.ts:1498-1501only checksaccount?.accountData?.policyIDs?.includes(policyID)and missesaccount?.accountData?.additionalData?.policyID === policyID.if (oldBankAccountID !== undefined && String(bankAccountID) === oldBankAccountID && currentAchAccount?.bankAccountID === bankAccountID)) is not guarded by!shouldClearBankAccountID.policyIDback intooptimisticBankAccountList[bankAccountID]even when disabling payments.WorkflowsPaymentsTab.tsx:317-337):Because
isBankAccountFullySetupandbankAccountConnectedToWorkspaceremain truthy in Onyx after disabling Payments, toggling Payments back on evaluates(!isBankAccountFullySetup && !bankAccountConnectedToWorkspace)asfalse, selectsREIMBURSEMENT_YESinstead ofREIMBURSEMENT_MANUAL, and passes the stalepolicy?.achAccount?.bankAccountIDback tosetWorkspaceReimbursement.What changes do you think we should make in order to solve the problem?
In
src/pages/workspace/workflows/tabs/WorkflowsPaymentsTab.tsx:324-337:Pass
bankAccountListtosetWorkspaceReimbursement(and only passpolicy?.achAccountdetails when enabling with an active account):In
src/libs/actions/Policy/Policy.ts:1496-1651(setWorkspaceReimbursement):const shouldClearBankAccountID = reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO;at the top ofsetWorkspaceReimbursement.oldBankAccountIDagainst bothpolicyIDsandadditionalData.policyID:!shouldClearBankAccountID:achAccountinoptimisticDatawhenshouldClearBankAccountIDistrue:ONYXKEYS.BANK_ACCOUNT_LISToptimistic and failure updates:oldBankAccountIDexists, removepolicyIDfromaccountData.policyIDsand setaccountData.additionalData.policyIDtonull(with corresponding rollback infailureData).policyIDontooptimisticBankAccountList[bankAccountID](andfailureBankAccountList[bankAccountID]) when!shouldClearBankAccountID && bankAccountID !== undefined.What alternative solutions did you explore? (Optional)
bankAccountConnectedToWorkspaceon!!policy?.achAccount?.bankAccountIDinWorkflowsPaymentsTab.tsx: Rejected because partially set-up bank accounts (SETUP,PENDING,VERIFYINGchecked viaisBankAccountPartiallySetup(state)at line 155) do not populatepolicy.achAccountand rely onbankAccountList[id].accountData.additionalData.policyID === policy.id. Leaving stalepolicyIDentries inONYXKEYS.BANK_ACCOUNT_LISTalso breaksgetEligibleExistingBusinessBankAccountsat line 158.FitseTLT commentedon Nov 5, 2026
@MelvinBot can u put a proposal
MelvinBot commentedon Nov 5, 2026
Proposal
What is the root cause of that problem?
Turning Payments off clears the bank account in the API request, but the optimistic update retains the old
policy.achAccount. The Payments toggle also omitsbankAccountListwhen calling the action, leaving its workspace associations untouched.Re-enabling Payments trusts either source, so the stale account reappears—even if a server update has already cleared
policy.achAccount.Code evidence and verification limits
additionalData.policyID, independently ofpolicy.achAccount.bankAccountList.This confirms a client-state defect through code inspection. I have not independently reproduced the UI behavior or inspected server responses; a response that actively restores stale associations would require additional investigation.
What changes do you think we should make in order to solve the problem?
Fix the stored state rather than hiding the account in the component:
bankAccountListinto the reimbursement action from the Payments toggle.policy.achAccountand detach the workspace from matching bank-list entries. Remove only this workspace frompolicyIDs; clearadditionalData.policyIDonly when it matches this workspace. Preserve the bank accounts themselves and other workspace associations. Handle accounts associated only throughadditionalData, including incomplete setups without an ACH account.Regression coverage
No code changes or tests were run for this proposal.
What alternative solutions did you explore? (Optional)
Requiring
policy.achAccountbefore displaying a bank-list account would hide legitimate incomplete setups. Clearing the entire bank list would affect unrelated accounts. Passing the list alone is also insufficient because the action currently reattaches the selected account.Related report: [Exploratory] Selecting same BA, add BA RHP shown after toggle off/on payments concerns the destination after clicking an account following the same toggle sequence; it is potentially related, not a confirmed duplicate.
Next Steps for Contributor+ team:
To accept:
@MelvinBot implementthis proposal to create a draft PR.To refine:
@MelvinBot <your feedback>To reject: Explain why you are rejecting Melvin's proposal.
FitseTLT commentedon Nov 5, 2026
@MelvinBot implement
MelvinBot commentedon Nov 5, 2026
🤖 Web test steps verification results: ❌ fail
Blocked on dev NewDot web: the handed-off session showed a blank page. Both initial and post-wait snapshots returned 0 nodes, so the fix could not be verified; no state was seeded or changed.
Workspace admin, Payments enabled, and connected business bank account
Preconditions could not be inspected: blank page, 0 snapshot nodes, and Workspaces wait timed out.Payments off/on disconnects the previous bank and shows Add bank account
Not executed because the app UI was unavailable.Disconnection persists after refresh
Not executed; refresh is also prohibited by the web session policy.Payments off/on offline
Not executed; offline network control is outside supported web CLI capabilities.Implementation: Created draft PR Detach workspace bank accounts when disabling Payments, assigned to
FitseTLT, with PullerBear review requested. It clears the workspace connection, preserves other workspaces' links, and restores state on failure.Automated checks passed: 37,160 Jest tests; final focused run of 263 tests; lint, TypeScript, formatting, spelling, component compiler check, Storybook smoke test, and coding-standards review. Command substitutions and the browser blocker are documented in the PR.
Please complete manual verification before marking the draft ready for review, or ask me to mark it ready after verification.
view run · no recording available
jeffrey-graham commentedon Nov 7, 2026
melvin-bot commentedon Nov 7, 2026
📣 @jeffrey-graham! 📣
Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork.
Please follow these steps:
Format:
melvin-bot commentedon Nov 7, 2026
📣 @ronanchnlps-bit! 📣
Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork.
Please follow these steps:
Format:
TassioSales commentedon Nov 8, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
After disabling and re-enabling Payments in a workspace, previously connected bank accounts remain visible in the UI until the page is refreshed.
What is the root cause of that problem?
In
WorkspacePaymentsPage.tsxandPolicy.ts:When payments are toggled off, the policy configuration is disabled on the backend, but the local Onyx cache for
bankAccountListand workspace reimbursement accounts is not cleared or invalidated locally. When payments are toggled back on, the component reads the lingering cached bank account records from Onyx before the server syncs.What changes do you think we should make in order to solve the problem?
Policy.ts(setWorkspaceReimbursementAccount/disablePayments):WorkspacePaymentsPage.tsx:What alternative solutions did you explore? (Optional)
Force reloading the browser window on payment toggle, but proper Onyx cache management is smoother and avoids full page reloads.