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 - Save button does not disappear after resetting currency on total spend footer #104014
Version Number: 9.5.9-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:#100674 Email or phone of affected tester (no customers):[email protected] Issue reported by: Applause Internal Team Bug source: Exploratory - Significant User Experience Deterioration Device used: Mac 26.5 / Chrome App Component: Search
Action Performed:
Precondition:
Enable spendFooterSelectors beta.
Go to staging.new.expensify.com
Go to workspace chat.
Create an expense.
Go to Spend > Expenses..
Click total spend on the footer.
Click Currency.
Select any currency > Apply.
Click total spend on the footer.
Click Currency.
Click Reset.
Expected Result:
Save button next to search field should be removed after resetting currency on total spend footer.
Actual Result:
Save button next to search field does not disappear after resetting currency on total spend footer.
👋 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.
Root Cause: Reset doesn't remove the currency from the query. It writes the default currency into it, for example footerCurrency:USD. Any footer filter left in the query makes the search savable, so the Save button stays.
Recommendation: roll forward with a one-line fix. Reverting would remove a 45-file feature that is behind the spendFooterSelectors beta. In SearchSelectionFooter.tsx, drop the currency from the query when it matches the search's default:
Add a unit test: pick EUR, then Reset. Expect no footerCurrency in the query and isSearchQuerySavable to return false.
Investigation details
Reset picks the default explicitly.handleCurrencyChange turns Reset into item?.value ?? defaultCurrency (SearchPageFooter.tsx:118-129). The default is searchTargetCurrency, which is the active policy's output currency or USD (SearchSelectionFooter.tsx:163). This was harmless before the PR, because the currency only lived in component state.
The PR writes the currency into the URL.handleFooterCurrencyChange calls applyFooterSelection({footerCurrency: currency}), which navigates to a rebuilt query (SearchSelectionFooter.tsx:653-672).
Only the default count and total are dropped. In getQueryWithFooterSelection, isDefaultSelection covers footerTotal and footerCount but not footerCurrency (SearchQueryUtils.ts:806-812).
Why the fix works:getQueryWithFooterSelection merges the new selection over the query's current one ({...getFooterSelectionFromQuery(queryJSON), ...selection}). An explicit footerCurrency: undefined therefore overrides the old value, and the !value check skips it. Totals don't change, because the server already uses the policy currency when the query names none.
Alternative fix: pass the default currency into getQueryWithFooterSelection and add it to isDefaultSelection. This keeps all default-dropping logic in one place, but it changes the function's signature.
Please re-state the problem that we are trying to solve in this issue.
With the spendFooterSelectors beta on, the Save button next to the search field stays visible after you reset the footer currency.
What is the root cause of that problem?
Reset doesn't remove the currency from the search query. It writes the default currency in explicitly, for example footerCurrency:USD.
Reset turns "no selection" into the default currency, item?.value ?? defaultCurrency (SearchPageFooter.tsx:118-129). That default is searchTargetCurrency: the active policy's output currency, or USD (SearchSelectionFooter.tsx:163).
handleFooterCurrencyChange passes that currency to applyFooterSelection, which writes it into the URL query (SearchSelectionFooter.tsx:664-672).
getQueryWithFooterSelection leaves out the default count and the default total, but not the default currency (SearchQueryUtils.ts:806-812).
Because of the leftover footerCurrency filter, isSearchQuerySavable reports the query as different from the default search, so the Save button shows (useSearchFiltersBar.tsx:247).
Applying the default currency directly, without Reset, has the same effect.
What changes do you think we should make in order to solve the problem?
In handleFooterCurrencyChange in SearchSelectionFooter.tsx, pass footerCurrency: undefined to applyFooterSelection when the chosen currency equals searchTargetCurrency. Otherwise pass the chosen currency as it does today.
This works without other changes:
getQueryWithFooterSelection merges the new selection over the query's current one, so an explicit undefined replaces the old currency. The existing !value check then skips it.
The local footer state still records the pick, so the footer shows the right currency until the URL updates.
The totals don't change, because the server already uses the policy currency when the query names none.
Add a unit test: pick EUR, then Reset. The query should have no footerCurrency, and isSearchQuerySavable should return false.
What alternative solutions did you explore? (Optional)
Pass the default currency into getQueryWithFooterSelection and add a footerCurrency case to isDefaultSelection. This keeps all the "leave defaults out" logic in one place, but it changes the function's signature and every caller.
Next Steps for Contributor+ team: To accept:@MelvinBot implement [this](https://github.com/Expensify/App/issues/104014#issuecomment-6183730622) to create a draft PR. To refine:@MelvinBot <your feedback> To reject: Explain why you are rejecting Melvin's proposal.
Activity
applause-bot commentedon Oct 14, 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/a29a06e91bd7d5753a8dada1a4a593cdc56548b0968c0265f0e9eb1e094d1048
melvin-bot commentedon Oct 14, 2026
You have been assigned to this deploy blocker because you recently merged this PR: #100674
github-actions commentedon Oct 14, 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 Oct 14, 2026
@JS00001 @mkhutornyi you have been assigned to this deploy blocker because you reviewed the offending PR: #100674
melvin-bot commentedon Oct 14, 2026
@truph01 you have been assigned to this deploy blocker because you authored the offending PR: #100674
melvin-bot commentedon Oct 14, 2026
💬 A slack conversation has been started in #expensify-open-source
MelvinBot commentedon Oct 14, 2026
Deploy Blocker Analysis
Causing PR: feat: Add count and spend total selectors to the Spend footer (high confidence). It merged 2026-10-13 and is on the current deploy checklist.
Root Cause: Reset doesn't remove the currency from the query. It writes the default currency into it, for example
footerCurrency:USD. Any footer filter left in the query makes the search savable, so the Save button stays.Recommendation: roll forward with a one-line fix. Reverting would remove a 45-file feature that is behind the
spendFooterSelectorsbeta. InSearchSelectionFooter.tsx, drop the currency from the query when it matches the search's default:Add a unit test: pick EUR, then Reset. Expect no
footerCurrencyin the query andisSearchQuerySavableto return false.Investigation details
handleCurrencyChangeturns Reset intoitem?.value ?? defaultCurrency(SearchPageFooter.tsx:118-129). The default issearchTargetCurrency, which is the active policy's output currency or USD (SearchSelectionFooter.tsx:163). This was harmless before the PR, because the currency only lived in component state.handleFooterCurrencyChangecallsapplyFooterSelection({footerCurrency: currency}), which navigates to a rebuilt query (SearchSelectionFooter.tsx:653-672).getQueryWithFooterSelection,isDefaultSelectioncoversfooterTotalandfooterCountbut notfooterCurrency(SearchQueryUtils.ts:806-812).canSavecomes fromisSearchQuerySavable(useSearchFiltersBar.tsx:247). That function ignoresgroupCurrencybut not footer filters (SearchQueryUtils.ts:1241-1253).Why the fix works:
getQueryWithFooterSelectionmerges the new selection over the query's current one ({...getFooterSelectionFromQuery(queryJSON), ...selection}). An explicitfooterCurrency: undefinedtherefore overrides the old value, and the!valuecheck skips it. Totals don't change, because the server already uses the policy currency when the query names none.Alternative fix: pass the default currency into
getQueryWithFooterSelectionand add it toisDefaultSelection. This keeps all default-dropping logic in one place, but it changes the function's signature.Other PRs ruled out: Fix group-by:from total going down when an expense is created offline touches only
SearchUpdate.ts.Code review rule: I'm not proposing one. Catching this requires knowing each filter's default value, and a pattern check can't detect that.
Next Steps: Reply with
@MelvinBot implement thisto create a draft PR, or@MelvinBot <your feedback>to refine this analysis.view run
mkhutornyi commentedon Oct 14, 2026
Behind not blocker.
Also, not reproducible in non-beta account
JS00001 commentedon Oct 14, 2026
this is behind a beta, lets fix this though @mkhutornyi @truph01, going to link it to the original issue
truph01 commentedon Oct 15, 2026
@MelvinBot Post proposal
MelvinBot commentedon Oct 15, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
With the
spendFooterSelectorsbeta on, the Save button next to the search field stays visible after you reset the footer currency.What is the root cause of that problem?
Reset doesn't remove the currency from the search query. It writes the default currency in explicitly, for example
footerCurrency:USD.item?.value ?? defaultCurrency(SearchPageFooter.tsx:118-129). That default issearchTargetCurrency: the active policy's output currency, or USD (SearchSelectionFooter.tsx:163).handleFooterCurrencyChangepasses that currency toapplyFooterSelection, which writes it into the URL query (SearchSelectionFooter.tsx:664-672).getQueryWithFooterSelectionleaves out the default count and the default total, but not the default currency (SearchQueryUtils.ts:806-812).footerCurrencyfilter,isSearchQuerySavablereports the query as different from the default search, so the Save button shows (useSearchFiltersBar.tsx:247).Applying the default currency directly, without Reset, has the same effect.
What changes do you think we should make in order to solve the problem?
In
handleFooterCurrencyChangeinSearchSelectionFooter.tsx, passfooterCurrency: undefinedtoapplyFooterSelectionwhen the chosen currency equalssearchTargetCurrency. Otherwise pass the chosen currency as it does today.This works without other changes:
getQueryWithFooterSelectionmerges the new selection over the query's current one, so an explicitundefinedreplaces the old currency. The existing!valuecheck then skips it.Add a unit test: pick EUR, then Reset. The query should have no
footerCurrency, andisSearchQuerySavableshould return false.What alternative solutions did you explore? (Optional)
Pass the default currency into
getQueryWithFooterSelectionand add afooterCurrencycase toisDefaultSelection. This keeps all the "leave defaults out" logic in one place, but it changes the function's signature and every caller.Next Steps for Contributor+ team:
To accept:
@MelvinBot implement [this](https://github.com/Expensify/App/issues/104014#issuecomment-6183730622)to create a draft PR.To refine:
@MelvinBot <your feedback>To reject: Explain why you are rejecting Melvin's proposal.