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
[$175] Company Cards - Cannot assign new TD Canada Trust card (card ending in xxxx not listed in dashboard dropdown after successful "Assign new cards") #104352
Version Number: Reproducible in staging?: Needs Reproduction (Reproduction blocked) Reproducible in production?: Needs Reproduction If this was caught during regression testing, add the test name, ID and link from BrowserStack: Email or phone of affected tester (no customers): Logs:https://stackoverflow.com/c/expensify/questions/4856 Expensify/Expensify Issue URL: Issue reported by:@scerrato88 Slack conversation (hyperlinked to channel name): #Expensify Bugs
Action Performed:
Connect a TD Canada Trust card feed to a workspace that already has ~50 (or more) accounts under that connection.
As admin (master login), go to Settings > Assign new cards.
Attempt to assign a new card ending in xxxx.
Confirm the "successfully updated" message appears.
Go to the card dashboard and check whether the card is listed.
Check whether the company/account appears in the assign-card dropdown.
Expected Result:
The newly assigned card should appear under the card dashboard, and the company/account should be listed in the dropdown when assigning cards.
Actual Result:
The card does not appear under the card dashboard despite a successful update message.
The company is not listed in the dropdown.
Workaround:
Unknown
Needs confirmation:
Whether there's a hard cap (e.g., 50 accounts) on how many accounts Plaid/TD returns per connection
Platforms:
Select the officially supported platforms where the issue was reproduced:
⚠️Preliminary analysis (low confidence) — treat as a starting point, not a conclusion.
This appears to be a backend/internal issue. A separate internal investigation is needed.
The App does not cap the assign-card list. For Plaid and direct feeds, the dropdown shows the feed's accountList exactly as the backend sends it, minus cards that are already assigned (src/libs/CardUtils.ts:1372-1380). If a TD account is missing, the backend list for that connection most likely never included it.
The success message doesn't prove a card was created. The App adds no card on its side, so a card appears only if the backend sends one back (src/libs/actions/CompanyCards.ts:466-551).
I couldn't verify the cause because:
The issue has no cardholder email, workspace or domain ID, feed name, or card last 4, so logs can't be checked.
The steps ("Settings > Assign new cards", "successfully updated") look like Expensify Classic, not New Expensify.
To confirm, an internal engineer should check:
How many entries the stored account list holds for this TD feed. If it holds about 50, the cap is upstream of the App.
Whether the newly issued card ever reached the connection. With Plaid, accounts opened after the first connection usually need the admin to reconnect and select them. Fixing the connection in New Expensify may add them.
What the backend returned for the assignment request, and whether it created a card.
Possible App-side contributor
getFilteredCardList hides any account whose masked name (for example CREDIT CARD...1234) matches a card assigned in any workspace the admin can see. With 50+ accounts on one login, two accounts can share a masked name. isCardAlreadyAssigned was already limited to the current workspace for this reason, but getFilteredCardList was not. This could hide an account from the dropdown. It does not explain a card missing from the dashboard after a successful assignment.
Next Steps: Reply with @MelvinBot <your feedback> to refine this analysis. Adding the cardholder email, workspace ID, and card last 4 would let the logs be checked.
changed the title [-]Company Cards - Cannot assign new TD Canada Trust card (card ending in xxxx not listed in dashboard dropdown after successful "Assign new cards")[/-][+][$175] Company Cards - Cannot assign new TD Canada Trust card (card ending in xxxx not listed in dashboard dropdown after successful "Assign new cards")[/+]on Oct 19, 2026
Please re-state the problem that we are trying to solve in this issue.
When assigning a company card from a TD Canada Trust feed (or any direct Plaid/OAuth feed with many accounts/workspaces), a newly added card does not appear in the card assignment dropdown or is omitted from the dashboard dropdown after assignment.
What is the root cause of that problem?
In src/libs/CardUtils.ts:1361-1380 inside getFilteredCardList:
// Get cards assigned across all workspacesconstallWorkspaceAssignedCards=newSet<string>();for(constworkspaceCardsofObject.values(workspaceCardFeeds??{})){forEachAssignedCard(workspaceCards,(card)=>{if(!card.cardName){return;}allWorkspaceAssignedCards.add(card.cardName);});}// For direct feeds (Plaid/OAuth): displayName === cardIdentifierif(accountList){returnfilterAmexDirectParentCard(accountList,feedName).filter((cardName)=>!assignedCards.has(cardName)&&!allWorkspaceAssignedCards.has(cardName))
For direct feeds (Plaid/OAuth), the client-side identifier is the masked card name (e.g., TD Business...1234 or CREDIT CARD...xxxx), which is not unique across accounts or workspaces when an enterprise has 50+ cards.
In isCardAlreadyAssigned (src/libs/CardUtils.ts:2242-2251), Expensify engineers explicitly noted:
"Only flag a card already assigned within the CURRENT workspace/domain (and feed). Direct feeds (Plaid/OAuth) must NOT be matched across other workspaces: the only identifier the client has for them is the masked display name... Genuine cross-account duplicates are rejected server-side by ASSIGN_COMPANY_CARD — the same path Expensify Classic uses, which is why the identical assignment succeeds there."
While isCardAlreadyAssigned was corrected to scope to the current workspace, getFilteredCardList was inadvertently left accumulating allWorkspaceAssignedCards across every workspace the admin has access to.
Consequently, if another card in any workspace shares the same masked name suffix, allWorkspaceAssignedCards.has(cardName) returns true, erroneously filtering the card out of the assignment dropdown in NewDot, while Classic succeeds without cross-workspace client-side filtering.
What changes do you think we should make in order to solve the problem?
In src/libs/CardUtils.ts:
In getFilteredCardList, remove cross-workspace filtering for direct feeds (accountList). Only filter out assignedCards belonging to the specific current workspace and feed being configured:
For commercial feeds, preserve workspace scoping consistent with isCardAlreadyAssigned.
What alternative solutions did you explore? (Optional)
Attempting to synthesize unique composite keys from client data. This was rejected because Plaid/OAuth feeds provide the masked account name as the display key, and the server-side command (ASSIGN_COMPANY_CARD) already enforces true database-level duplicate validation.
Automated Tests
In tests/unit/CardUtilsTest.ts:
Add test case verifying that getFilteredCardList displays a direct feed card in workspace A even when a card with an identical masked name exists in workspace B under workspaceCardFeeds.
Assert that only cards assigned within the target workspace/feed (assignedCards) are filtered out.
VERDICT: POST
ROOT_CAUSE_ONELINER: After importPlaidAccounts succeeds, the client's CARD_FEEDS Onyx key is never refreshed — successData only clears ASSIGN_CARD.isRefreshing, so CardSelectionStep's accountList-based card list remains stale and the new card never appears.
PROPOSAL_TYPE: FIRST
AUTOPOST_SAFE: YES
Please re-state the problem that we are trying to solve in this issue.
When assigning a company card from a TD Canada Trust feed (or any direct Plaid/OAuth feed with ~50+ accounts or across multiple workspaces), newly connected/assigned cards do not appear in the assignment dropdown or are missing from the dashboard dropdown even after a "successfully updated" confirmation message.
What is the root cause of that problem?
There are two root causes:
Cross-Workspace Filtering in getFilteredCardList (CardUtils.ts:1361-1380):
In src/libs/CardUtils.ts:1361-1375, getFilteredCardList aggregates all assigned cards across every workspace via allWorkspaceAssignedCards:
For direct feeds (Plaid/OAuth), cardName is merely the masked account title/suffix (e.g. TD Business...xxxx or CREDIT CARD...xxxx), which is not unique across accounts or workspaces when an enterprise has 50+ cards.
As explicitly documented in isCardAlreadyAssigned (src/libs/CardUtils.ts:2242-2248):
"Direct feeds (Plaid/OAuth) must NOT be matched across other workspaces: the only identifier the client has for them is the masked display name... which is not unique across accounts. Genuine cross-account duplicates are rejected server-side by ASSIGN_COMPANY_CARD — the same path Expensify Classic uses, which is why the identical assignment succeeds there."
While isCardAlreadyAssigned was correctly updated to restrict checks to the current workspace, getFilteredCardList was left filtering cross-workspace. As a result, if any card in another workspace shares an identical masked display name, allWorkspaceAssignedCards.has(cardName) returns true and silently strips the card from the dropdown.
Stale CARD_FEEDS in importPlaidAccounts (Plaid.ts:184-198):
In src/libs/actions/Plaid.ts:184-198, importPlaidAccounts executes API.write(WRITE_COMMANDS.IMPORT_PLAID_ACCOUNTS, parameters, onyxData). However, successData only clears ASSIGN_CARD.isRefreshing: null. It never merges or refreshes CARD_FEEDS in Onyx. Because CardSelectionStep.tsx:60 and getFilteredCardList read cardFeeds?.[feed]?.accountList, the client retains the stale account list in Onyx after the Plaid import finishes until the user explicitly refreshes the app.
What changes do you think we should make in order to solve the problem?
Remove Cross-Workspace Filtering for Direct Feeds:
In src/libs/CardUtils.ts:1361-1380, align getFilteredCardList with the architectural pattern in isCardAlreadyAssigned: for direct feeds (accountList), only filter against assignedCards within the current workspace and feed:
Refresh CARD_FEEDS upon Successful Plaid Import:
In src/libs/actions/Plaid.ts:184-198, ensure importPlaidAccounts updates CARD_FEEDS or refetches the policy card feeds upon completion so that cardFeeds?.[feed]?.accountList contains the freshly imported cards immediately.
Tests:
In tests/unit/CardUtilsTest.ts:
Add a test verifying that getFilteredCardList keeps a direct feed card available for assignment in workspace A even when an identical masked name exists in workspace B in workspaceCardFeeds.
Assert that only cards assigned within the target workspace/feed (assignedCards) are filtered out.
What alternative solutions did you explore? (Optional)
Attempting to synthesize composite keys on the client using account indexes or hashes. This was rejected because Plaid direct feeds use the masked account name as the display key, and backend duplicate checking in ASSIGN_COMPANY_CARD already authoritatively prevents actual duplicate card assignments without needing client-side cross-workspace collisions.
Activity
MelvinBot commentedon Oct 19, 2026
This appears to be a backend/internal issue. A separate internal investigation is needed.
The App does not cap the assign-card list. For Plaid and direct feeds, the dropdown shows the feed's
accountListexactly as the backend sends it, minus cards that are already assigned (src/libs/CardUtils.ts:1372-1380). If a TD account is missing, the backend list for that connection most likely never included it.The success message doesn't prove a card was created. The App adds no card on its side, so a card appears only if the backend sends one back (
src/libs/actions/CompanyCards.ts:466-551).I couldn't verify the cause because:
To confirm, an internal engineer should check:
Possible App-side contributor
getFilteredCardListhides any account whose masked name (for exampleCREDIT CARD...1234) matches a card assigned in any workspace the admin can see. With 50+ accounts on one login, two accounts can share a masked name.isCardAlreadyAssignedwas already limited to the current workspace for this reason, butgetFilteredCardListwas not. This could hide an account from the dropdown. It does not explain a card missing from the dashboard after a successful assignment.Next Steps: Reply with
@MelvinBot <your feedback>to refine this analysis. Adding the cardholder email, workspace ID, and card last 4 would let the logs be checked.view run
melvin-bot commentedon Oct 19, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @thelullabyy (
External)[-]Company Cards - Cannot assign new TD Canada Trust card (card ending in xxxx not listed in dashboard dropdown after successful "Assign new cards")[/-][+][$175] Company Cards - Cannot assign new TD Canada Trust card (card ending in xxxx not listed in dashboard dropdown after successful "Assign new cards")[/+]melvin-bot commentedon Oct 19, 2026
Job added to Upwork: https://www.upwork.com/jobs/~022112169735580111595
camesenin commentedon Oct 19, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
When assigning a company card from a TD Canada Trust feed (or any direct Plaid/OAuth feed with many accounts/workspaces), a newly added card does not appear in the card assignment dropdown or is omitted from the dashboard dropdown after assignment.
What is the root cause of that problem?
In
src/libs/CardUtils.ts:1361-1380insidegetFilteredCardList:TD Business...1234orCREDIT CARD...xxxx), which is not unique across accounts or workspaces when an enterprise has 50+ cards.isCardAlreadyAssigned(src/libs/CardUtils.ts:2242-2251), Expensify engineers explicitly noted:isCardAlreadyAssignedwas corrected to scope to the current workspace,getFilteredCardListwas inadvertently left accumulatingallWorkspaceAssignedCardsacross every workspace the admin has access to.allWorkspaceAssignedCards.has(cardName)returnstrue, erroneously filtering the card out of the assignment dropdown in NewDot, while Classic succeeds without cross-workspace client-side filtering.What changes do you think we should make in order to solve the problem?
In
src/libs/CardUtils.ts:getFilteredCardList, remove cross-workspace filtering for direct feeds (accountList). Only filter outassignedCardsbelonging to the specific current workspace and feed being configured:isCardAlreadyAssigned.What alternative solutions did you explore? (Optional)
Attempting to synthesize unique composite keys from client data. This was rejected because Plaid/OAuth feeds provide the masked account name as the display key, and the server-side command (
ASSIGN_COMPANY_CARD) already enforces true database-level duplicate validation.Automated Tests
In
tests/unit/CardUtilsTest.ts:getFilteredCardListdisplays a direct feed card in workspace A even when a card with an identical masked name exists in workspace B underworkspaceCardFeeds.assignedCards) are filtered out.Contributor details
Your Expensify account email: [email protected]
Upwork Profile Link: https://www.upwork.com/freelancers/~0170d6b02e9440e604
melvin-bot commentedon Oct 19, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
j3ffffff commentedon Oct 19, 2026
VERDICT: POST
ROOT_CAUSE_ONELINER: After
importPlaidAccountssucceeds, the client'sCARD_FEEDSOnyx key is never refreshed —successDataonly clearsASSIGN_CARD.isRefreshing, soCardSelectionStep'saccountList-based card list remains stale and the new card never appears.PROPOSAL_TYPE: FIRST
AUTOPOST_SAFE: YES
sijo0218 commentedon Oct 19, 2026
Contributor details
Your Expensify account email: [email protected]
Upwork Profile Link: https://www.upwork.com/freelancers/~011091133bbb09cd1c
Proposal
Please re-state the problem that we are trying to solve in this issue.
When assigning a company card from a TD Canada Trust feed (or any direct Plaid/OAuth feed with ~50+ accounts or across multiple workspaces), newly connected/assigned cards do not appear in the assignment dropdown or are missing from the dashboard dropdown even after a "successfully updated" confirmation message.
What is the root cause of that problem?
There are two root causes:
getFilteredCardList(CardUtils.ts:1361-1380):In
src/libs/CardUtils.ts:1361-1375,getFilteredCardListaggregates all assigned cards across every workspace viaallWorkspaceAssignedCards:And then filters direct feeds (
accountList) with:For direct feeds (Plaid/OAuth),
cardNameis merely the masked account title/suffix (e.g.TD Business...xxxxorCREDIT CARD...xxxx), which is not unique across accounts or workspaces when an enterprise has 50+ cards.As explicitly documented in
isCardAlreadyAssigned(src/libs/CardUtils.ts:2242-2248):While
isCardAlreadyAssignedwas correctly updated to restrict checks to the current workspace,getFilteredCardListwas left filtering cross-workspace. As a result, if any card in another workspace shares an identical masked display name,allWorkspaceAssignedCards.has(cardName)returnstrueand silently strips the card from the dropdown.CARD_FEEDSinimportPlaidAccounts(Plaid.ts:184-198):In
src/libs/actions/Plaid.ts:184-198,importPlaidAccountsexecutesAPI.write(WRITE_COMMANDS.IMPORT_PLAID_ACCOUNTS, parameters, onyxData). However,successDataonly clearsASSIGN_CARD.isRefreshing: null. It never merges or refreshesCARD_FEEDSin Onyx. BecauseCardSelectionStep.tsx:60andgetFilteredCardListreadcardFeeds?.[feed]?.accountList, the client retains the stale account list in Onyx after the Plaid import finishes until the user explicitly refreshes the app.What changes do you think we should make in order to solve the problem?
In
src/libs/CardUtils.ts:1361-1380, aligngetFilteredCardListwith the architectural pattern inisCardAlreadyAssigned: for direct feeds (accountList), only filter againstassignedCardswithin the current workspace and feed:CARD_FEEDSupon Successful Plaid Import:In
src/libs/actions/Plaid.ts:184-198, ensureimportPlaidAccountsupdatesCARD_FEEDSor refetches the policy card feeds upon completion so thatcardFeeds?.[feed]?.accountListcontains the freshly imported cards immediately.In
tests/unit/CardUtilsTest.ts:getFilteredCardListkeeps a direct feed card available for assignment in workspace A even when an identical masked name exists in workspace B inworkspaceCardFeeds.assignedCards) are filtered out.What alternative solutions did you explore? (Optional)
Attempting to synthesize composite keys on the client using account indexes or hashes. This was rejected because Plaid direct feeds use the masked account name as the display key, and backend duplicate checking in
ASSIGN_COMPANY_CARDalready authoritatively prevents actual duplicate card assignments without needing client-side cross-workspace collisions.melvin-bot commentedon Oct 19, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!