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
Spend- Click "Reconciliation - All Expenses" exported file not covered all expenses #102103
Version Number: 9.4.92-0 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:#101522 Email or phone of affected tester (no customers):applausetester+dk56@applause.expensifail.com Issue reported by: Applause Internal Team Bug source: Pull Request QA execution Device used: Windows 11 Home/Chrome App Component: Search
Action Performed:
Preconditions:
Import a transaction (csv) file to an account
Create a workspace, enable Company cards or the Expensify Card
Set the filter: Expense type: Card, Card: "card name", Display > Group by: Card
Click to select the card row
Click on "Export" button on bottom taskbar
Select "Reconciliation - All Expenses"
Open the downloaded file
Expected Result:
The resulting CSV covers every expense on the selected card — including expenses further down the list that were never scrolled into view — not only the rows that happened to be loaded on screen.
Actual Result:
The file only contains 1 expense.
Step 5 and Step 7 in PR is failed
👋 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.
The "Reconciliation - All Expenses" option on a card group selection only exists because of #101522, and that PR's own description states the positive branch was never verified in a browser (the CI account has no imported card transactions), so the very step QA failed is the step that was never exercised. Reverting restores production behaviour (no templates offered for a group selection) and touches only one source file plus its test file.
Assigned: @NikkiWines and @ZhenjaHorbach (approving reviewers of #101522) — already assigned by melvin-bot; the PR author is a bot, so no author assignment. Labels: No changes. DeployBlockerCash stays (App-side PR caused it, and the bug is not reproducible on production). DeployBlocker was never applied and is not being added.
📋 Detailed Analysis
Evidence
The reported flow is brand new: before #101522, every export template was hidden as soon as a group row was ticked, so "Export → Reconciliation - All Expenses" on a card group row could not be reached at all. That PR added the carve-out at useSearchBulkActions.ts#L1984-L1987 and the gate change at #L2250. This matches "Reproducible in production?: N/A - new feature".
It is the only PR on the current Deploy Checklist: New Expensify 2026-09-23 that touches this code path (src/hooks/useSearchBulkActions.ts, merged 2026-09-22, right before the 9.4.92 staging build).
The PR body itself flags the gap: "The positive branch could not be exercised — the CI test account has no imported card transactions… Steps 2–7 below still need a manual run on an account with real card data." The failing QA steps are exactly steps 5 and 7.
The unit tests added by the PR only assert the arguments the App passes (reportIDList: [], transactionIDList: ['tx2'], jsonQuery contains cardID); nothing covers what the backend actually returns for that request, so they pass while the flow is broken.
Verification
Affected file: src/hooks/useSearchBulkActions.ts — it builds both the export menu and the export request.
gh pr view 101522 --json files → src/hooks/useSearchBulkActions.ts, tests/unit/hooks/useSearchBulkActionsExportTest.ts. The PR modifies exactly the file that owns the broken behaviour.
When a card group row is ticked, the export scope is carried entirely by the query, not by IDs — useSearchBulkActions.ts#L982-L1000 sends reportIDList: [], transactionIDList: [] (only individually-ticked rows survive) and a jsonQuery built by addSelectedGroupsFilter.
addSelectedGroupsFilter only swaps in a cardID: filter and rebuilds the query with buildSearchQueryString, which preserves the root keys — including groupBy and limit. So the request sent to ExportSearchWithTemplate is still a grouped query (type:expense groupBy:card cardID:<id>), and one selected card group resolves to one group row → the CSV contains a single line. That is precisely the reported symptom.
Two things in the repo show why the other export path does not hit this:
Everywhere else the App wants a group's transactions, it drops groupBy and limit. See buildSpecificGroupQuery and buildDateRangeGroupQuery, both with explicit comments that limit bounds the group count and must go when groupBy goes. addSelectedGroupsFilter keeps both.
Secondary defect on the same path (worth fixing whenever this is re-attempted): the template export serializes the query without searchKey (#L987-L993), while the CSV path deliberately includes it and warns that omitting it makes the exported set differ from the viewed set (#L1074-L1078) — which matters here because reconciliation searches are exactly the example named in that comment.
Roll-forward shape, if a revert is not wanted: build the template's jsonQuery from a flattened group query (groupBy: undefined, limit: undefined, same cardID: filter, plus searchKey) the way buildSpecificGroupQuery does, so the scope no longer depends on a group-expansion flag the command does not have. That still needs a manual run against an account with imported card transactions, which is why a revert is the safer call inside the deploy window.
Activity
applause-bot commentedon Sep 23, 2026
While Applause doesn't embed attachments for this bug, here are the links for quick view:
https://platform.applause.com/services/links/v1/external/2c0283f316a57f8e71f98addaf767e0aa52624e8278c24752c0150248b533122
melvin-bot commentedon Sep 23, 2026
You have been assigned to this deploy blocker because you recently merged this PR: #101522
melvin-bot commentedon Sep 23, 2026
@NikkiWines @ZhenjaHorbach you have been assigned to this deploy blocker because you reviewed the offending PR: #101522
github-actions commentedon Sep 23, 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:
melvin-bot commentedon Sep 23, 2026
💬 A slack conversation has been started in #expensify-open-source
MelvinBot commentedon Sep 23, 2026
🔍 Investigation Summary
Classification: Frontend bug
Causing PR: #101522 - "Extend Reconciliation - All Expenses export to any group-by:card selection" by @MelvinBot (High confidence that this PR exposed the broken flow; Medium-High confidence on the exact mechanism below, since the server side of the export can't be inspected from this repo)
Related Issues: [CFI] Add "Reconciliation - All Expenses" export option for NewDot (Workspace/Card admins + Card Statements search) (the issue PR #101522 implements)
Recommendation: REVERT
The "Reconciliation - All Expenses" option on a card group selection only exists because of #101522, and that PR's own description states the positive branch was never verified in a browser (the CI account has no imported card transactions), so the very step QA failed is the step that was never exercised. Reverting restores production behaviour (no templates offered for a group selection) and touches only one source file plus its test file.
Assigned: @NikkiWines and @ZhenjaHorbach (approving reviewers of #101522) — already assigned by melvin-bot; the PR author is a bot, so no author assignment.
Labels: No changes.
DeployBlockerCashstays (App-side PR caused it, and the bug is not reproducible on production).DeployBlockerwas never applied and is not being added.📋 Detailed Analysis
Evidence
useSearchBulkActions.ts#L1984-L1987and the gate change at#L2250. This matches "Reproducible in production?: N/A - new feature".src/hooks/useSearchBulkActions.ts, merged 2026-09-22, right before the 9.4.92 staging build).reportIDList: [],transactionIDList: ['tx2'],jsonQuerycontainscardID); nothing covers what the backend actually returns for that request, so they pass while the flow is broken.Verification
src/hooks/useSearchBulkActions.ts— it builds both the export menu and the export request.gh pr view 101522 --json files→src/hooks/useSearchBulkActions.ts,tests/unit/hooks/useSearchBulkActionsExportTest.ts. The PR modifies exactly the file that owns the broken behaviour.gh api repos/Expensify/App/commits?path=src/hooks/useSearchBulkActions.tsconfirms Extend Reconciliation - All Expenses export to any group-by:card selection #101522 is the most recent change to that file and the only staged change affecting group-scoped template exports.Root Cause
When a card group row is ticked, the export scope is carried entirely by the query, not by IDs —
useSearchBulkActions.ts#L982-L1000sendsreportIDList: [],transactionIDList: [](only individually-ticked rows survive) and ajsonQuerybuilt byaddSelectedGroupsFilter.addSelectedGroupsFilteronly swaps in acardID:filter and rebuilds the query withbuildSearchQueryString, which preserves the root keys — includinggroupByandlimit. So the request sent toExportSearchWithTemplateis still a grouped query (type:expense groupBy:card cardID:<id>), and one selected card group resolves to one group row → the CSV contains a single line. That is precisely the reported symptom.Two things in the repo show why the other export path does not hit this:
exportSearchItemsToCSVsendsisGroupExport(ExportSearchItemsToCSVParams.ts#L11), the flag added in [Payment due @thelullabyy] Fix mixed group export selection together with paired Auth/Web changes, so the backend expands a grouped query into its individual expenses and merges them withtransactionIDList.ExportSearchWithTemplateParamshas no such parameter, so the template export has no way to say "expand these groups". Every other caller ofqueueExportSearchWithTemplate(e.g.useExportActions.ts#L156-L167) sendsjsonQuery: '{}'plus explicit IDs, so Extend Reconciliation - All Expenses export to any group-by:card selection #101522 is the first code to send a grouped query to that command on a reachable path.groupByandlimit. SeebuildSpecificGroupQueryandbuildDateRangeGroupQuery, both with explicit comments thatlimitbounds the group count and must go whengroupBygoes.addSelectedGroupsFilterkeeps both.Secondary defect on the same path (worth fixing whenever this is re-attempted): the template export serializes the query without
searchKey(#L987-L993), while the CSV path deliberately includes it and warns that omitting it makes the exported set differ from the viewed set (#L1074-L1078) — which matters here because reconciliation searches are exactly the example named in that comment.Roll-forward shape, if a revert is not wanted: build the template's
jsonQueryfrom a flattened group query (groupBy: undefined,limit: undefined, samecardID:filter, plussearchKey) the waybuildSpecificGroupQuerydoes, so the scope no longer depends on a group-expansion flag the command does not have. That still needs a manual run against an account with imported card transactions, which is why a revert is the safer call inside the deploy window.IuliiaHerets commentedon Sep 24, 2026
Chrome / v9.4.92-7, still repro
bandicam.2026-09-24.12-07-42-421.mp4
IuliiaHerets commentedon Sep 24, 2026
But it is not repro on v9.4.92-8. The function is not there now
bandicam.2026-09-24.16-44-20-645.mp4
lakchote commentedon Sep 24, 2026
Closing.