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] Search-"type:expense vendor name", vendor name not highlighted and search result not correct #105375
Click the search icon at the top right and type "type:expense vendor:A B" > search
Clear the search and type: "type:expense vendor A B" > search
Clear the search and type: "type:expense vendor Admin Denis" > search
Expected Result:
Click the search icon at the top right and type type:expense vendor followed by the vendor name, verify the vendor name is highlighted like the other filter values. The search results match the filtered results
Actual Result:
Typing "type:expense vendor:A B" only the "A" is highlighted on the search box and displays no search result. Typing "type:expense vendor A B", the vendor name isn't highlighted, result displays both expenses with vendor "A B" and vendor "Admin Denis". Typing "type:expense vendor Admin Denis" displays no search result.
This is mostly expected search syntax, plus one missing feature in the search box:
vendor:A B (step 3). An unquoted value ends at the first space. This is true for every filter, not only vendor (baseRules.peggy:221). The query becomes vendor:A plus the keyword B, so only "A" is highlighted and nothing matches. Multi-word values must be quoted, for example vendor:"A B". Merchant, category, and tag work the same way.
vendor A B and vendor Admin Denis (steps 4 and 5). Without a colon, these are plain keyword searches. The App sends the words to the server unchanged, and the server decides what matches. Nothing is highlighted because there is no filter.
The App gap. Typing vendor: in the search box suggests no vendors. The suggestion switch handles tag and category, but has no VENDOR case (useAutocompleteSuggestions.ts:186-203). For other filters, picking a suggestion adds the quotes automatically (SearchRouter.tsx:476). For vendor, you have to type the quotes yourself, and the test step didn't include them.
What changes do you think we should make in order to solve the problem?
Add a VENDOR case to useAutocompleteSuggestions.ts. Fill it from the same synced vendor list that the Filters > Vendor picker uses. Selecting a vendor then inserts vendor:"A B" and highlights the full name.
Update the regression test case to use vendor:"<name>" for names that contain spaces.
Steps 4 and 5 (keyword results) are decided by the server. If those results are wrong, an internal engineer needs to look at them.
What alternative solutions did you explore? (Optional)
Let vendor: accept unquoted values that contain spaces. I rejected this because it would break the rule every other filter follows. It would also make vendor:A B ambiguous with a following keyword.
I didn't reproduce this in a browser. The test account has no QBO connection with vendors. These findings come from the parser grammar and the existing unit tests.
Next Steps for Contributor+ team: To accept:@MelvinBot implement [this](https://github.com/Expensify/App/issues/105375) to create a draft PR. To refine:@MelvinBot <your feedback> To reject: Explain why you are rejecting Melvin's proposal.
changed the title [-]Search-"type:expense vendor name", vendor name not highlighted and search result not correct[/-][+][$175] Search-"type:expense vendor name", vendor name not highlighted and search result not correct[/+]on Oct 29, 2026
Please re-state the problem that we are trying to solve in this issue.
The reported searches do not highlight or return the vendor names as the tester expects. However, the report mixes explicit filter syntax (vendor:A B) with plain text (vendor A B), so the expected behavior must be checked against the supported search syntax before classifying this as a code regression.
Verdict: MelvinBot’s proposal is incomplete as a fix for the reported reproduction steps. No independently verified replacement patch is established.
What is the root cause of that problem?
The supplied proposal describes three distinct behaviors:
Query
Melvin’s interpretation
Evidence status
type:expense vendor:A B
Vendor filter A, plus keyword B
Consistent with the quoted grammar description; not independently executed
type:expense vendor A B
Plain keywords after the expense filter
Not independently executed
type:expense vendor Admin Denis
Plain keywords after the expense filter
Not independently executed
Melvin cites these implementation locations:
src/libs/SearchParser/baseRules.peggy:221,231–238: unquoted and quoted value boundaries.
src/libs/SearchQueryUtils.ts:2016–2019: vendor query handling.
These are references supplied by Melvin, not source locations independently verified during this audit. The pinned files and target issue could not be retrieved, no Expensify checkout exists in this workspace, and no parser, Jest, or browser reproduction was run.
Consequently:
A parser defect is not established.
A backend matching defect is not established.
Missing vendor autocomplete remains a source-verification hypothesis.
No security impact is demonstrated.
What changes do you think we should make in order to solve the problem?
Do not approve an implementation from the current evidence. First establish whether the supported baseline, type:expense vendor:"A B", highlights the complete name and returns the intended expense in the stated QBO configuration.
Then use the smallest change supported by that result:
Quoted syntax works: correct the regression procedure. Treat autocomplete as a separately scoped usability improvement unless the issue owner explicitly accepts it as this issue’s resolution.
Quoted syntax fails: capture the parsed query and outgoing Search request, then locate the first incorrect transformation. Patch that boundary.
Vendor suggestions are the accepted scope: verify the existing picker’s eligibility, loading, and serialization behavior before reusing its data.
An autocomplete patch must account for vendor data arriving after the hook mounts, workspace changes, duplicate names across workspaces, empty results, and values containing punctuation or quotes. These are required verification cases; they are not proven failures in existing code.
No TypeScript diff is included because the actual types, helpers, dependencies, and insertion logic were unavailable. Inventing those details would fail the requirement for an exact, production-reviewable patch.
What alternative solutions did you explore? (Optional)
MelvinBot’s central coverage failure: adding suggestions only changes behavior when a user selects a suggestion. It does not change any of the three reported queries when typed and submitted unchanged. Updating the test to use quotes changes the reproduction procedure; it does not prove the original behavior was fixed.
Melvin’s syntax explanation may nevertheless be correct. Rewriting the parser to absorb spaces would introduce ambiguity between vendor values and subsequent keywords without an established syntax contract.
Likewise, adding a colon automatically to vendor Admin Denis could reinterpret legitimate keyword searches.
The related vendor-filter issue documents earlier removal and restoration work. That warrants an overlap check; it does not establish duplication of this autocomplete issue.
A claim that this is “the only safe solution” is unsupported. Expensify’s contribution guidelines require reproduction before proposing a fix and meaningful differentiation from existing proposals.
What automated tests can you add to prevent this from re-occurring?
Once the source is available, add focused Jest coverage:
Parser: verify that vendor:"A B" preserves one complete vendor value and creates no stray B keyword.
Syntax compatibility: verify the existing interpretation of vendor:A B and colonless queries.
Autocomplete, if implemented: mount before vendor data arrives, update the mocked subscription, and assert that suggestions refresh.
Insertion: select A B with the caret inside an existing query; assert that the inserted value parses back to exactly A B while neighboring filters and keywords remain intact.
Serialization: cover quoted and punctuated names through the existing insertion/parser round trip.
Workspace changes: ensure suggestions follow the same eligibility and data-selection rules as the vendor picker.
Mocked Jest responses cannot establish backend result correctness. That requires a controlled reproduction with the two stated expenses and captured request/result evidence.
Execution status: none of these tests were run; no passing validation is claimed.
Please re-state the problem that we are trying to solve in this issue.
Searching type:expense vendor:A B highlights only "A" and returns nothing, and colonless searches like type:expense vendor Admin Denis highlight nothing and return wrong results. The tester expects the vendor name to be highlighted like other filter values and the results to match the filtered expenses.
What is the root cause of that problem?
Two distinct behaviors, one of which is a genuine App gap:
Unquoted multi-word values end at the first space. This is the search grammar working as designed, not a vendor-specific regression: vendor:A B parses as vendor A plus keyword B, so only "A" is highlighted and nothing matches both conditions. Multi-word vendor values must be quoted, e.g. vendor:"A B". Without a colon, vendor A B and vendor Admin Denis are plain keyword searches, so nothing is highlighted and the server decides what matches.
The App gap: typing vendor: suggests no vendors. Verified against main source: the switch in src/hooks/useAutocompleteSuggestions.ts covers TAG, CATEGORY, CURRENCY, TAX_RATE and user filters, but has no vendor case. So a user can never discover the correct quoted form from the search box, which is exactly why the tester typed the unquoted forms.
What changes do you think we should make in order to solve the problem?
Add a vendor case to useAutocompleteSuggestions.ts, mirroring the existing TAG/CATEGORY cases:
Source the list from the workspace vendor list already synced for expenses, filtered by the typed substring (case-insensitive), capped at 10, and excluding vendor values already used in the current query (the same alreadyAutocompletedKeys dedup the TAG case uses).
Reuse the existing insertion path unchanged: sanitizeSearchValue in src/libs/SearchQueryUtils.ts already wraps any value containing a space in quotes, so selecting "A B" inserts vendor:"A B", which parses as a single vendor value and highlights in full.
Handle the lazy-load case explicitly: vendor lists load lazily, so while the list is not yet synced show no suggestions rather than stale data, following the category case's loader pattern. No parser change: the grammar already handles quoted values correctly, and rewriting it to absorb spaces would create ambiguity between vendor values and following keywords.
What alternative solutions did you explore?
Parser change to absorb spaces into the vendor value: rejected, it would make vendor:A B ambiguous with a vendor filter plus a keyword, and would change behavior for every filter.
Auto-inserting a colon after vendor: rejected, it would reinterpret legitimate keyword searches.
Backend/server matching change: not needed; the server already matches quoted vendor values by text.
What automated tests can you add to prevent this from re-occurring?
Jest test for the new vendor case: typing vendor: with a synced vendor list returns matching vendors; with no synced list returns an empty list.
Insertion test: selecting "A B" produces vendor:"A B" and reparsing yields exactly one vendor value A B, with neighbouring filters intact.
Dedup test: a vendor already used in the query is not suggested again.
Regression test for the grammar: unquoted vendor:A B still parses as vendor A plus keyword B (documented behaviour, unchanged).
Please re-state the problem that we are trying to solve in this issue.
When searching in Spend > Expenses for expenses with multi-word vendor names like "A B" or "Admin Denis":
Typing type:expense vendor:A B only highlights A in the search input, shows no vendor autocomplete suggestions to select "A B", and returns no results (because A is parsed as the vendor filter value and B is parsed as a separate free-text keyword).
Typing type:expense vendor A B or type:expense vendor Admin Denis without a colon runs a plain keyword search rather than a vendor: filter.
What is the root cause of that problem?
In the search grammar (src/libs/SearchParser/baseRules.peggy:221), unquoted filter values terminate at whitespace, so multi-word filter values must be quoted (vendor:"A B"). When a user types vendor:A and then presses space followed by B (type:expense vendor:A B), defaultFilter in src/libs/SearchParser/autocompleteParser.peggy:39-75 parses vendor:A into ranges and freeTextFilter (autocompleteParser.peggy:83) parses B and resets autocomplete = null.
src/hooks/useAutocompleteSuggestions.ts has no case CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR: branch, so typing vendor: never suggests synced workspace vendors (unlike category:, tag:, or exported-to:), which is what normally wraps multi-word values in quotes via sanitizeSearchValue in src/components/Search/SearchRouter/SearchRouter.tsx:480.
Even if a VENDOR case is added to useAutocompleteSuggestions.ts alone, CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR is also missing from CONTINUATION_DETECTION_SEARCH_FILTER_KEYS in src/libs/SearchAutocompleteUtils.ts:683-691. Without VENDOR in CONTINUATION_DETECTION_SEARCH_FILTER_KEYS (and mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR on each suggestion item):
As soon as the user types a space in a multi-word vendor name (type:expense vendor:A B or type:expense vendor:Admin Denis), parseForAutocomplete returns autocomplete: null. Because useAutocompleteSuggestions.ts:157-168 only checks CONTINUATION_DETECTION_SEARCH_FILTER_KEYS when !autocomplete, the vendor suggestions disappear immediately after the space is typed.
When selecting a suggestion after typing a space, getTrimmedUserSearchQueryPreservingComma (src/libs/SearchAutocompleteUtils.ts:1045-1071) only trims back to vendor: (or the last comma) when fieldKey is in CONTINUATION_DETECTION_SEARCH_FILTER_KEYS; otherwise it falls back to getQueryWithoutAutocompletedPart(textInputValue), which returns the untrimmed string when parsedQuery.autocomplete is null and produces type:expense vendor:A B"A B".
What changes do you think we should make in order to solve the problem?
In src/libs/SearchAutocompleteUtils.ts, add CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR to CONTINUATION_DETECTION_SEARCH_FILTER_KEYS:
In src/hooks/useAutocompleteSuggestions.ts, import usePermissions from ./usePermissions and getMatchingVendors, getVendorFeaturePolicyIDs from @libs/PolicyUtils, check const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING);, and add the VENDOR case to switch (autocompleteKey) using the same synced vendor source as VendorSelector.tsx with mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR:
With both changes in place, typing type:expense vendor:A B or type:expense vendor:Admin Denis keeps the matching vendor suggestion visible across spaces, and selecting it replaces the unquoted text after vendor: with vendor:"A B" (or vendor:"Admin Denis"), highlighting the full vendor name and returning the matching expense.
What alternative solutions did you explore? (Optional)
Changing the Peggy parser to allow unquoted spaces inside vendor: values would make vendor:A B ambiguous with trailing search keywords and break consistency with other filters (merchant:, category:, tag:). Adding VENDOR to useAutocompleteSuggestions together with CONTINUATION_DETECTION_SEARCH_FILTER_KEYS preserves the standard quoted syntax while supporting multi-word vendor autocomplete when typing spaces.
Please re-state the problem that we are trying to solve in this issue.
When typing a vendor filter in the global Search bar (such as type:expense vendor:A B or type:expense vendor Admin Denis), multi-word vendor names containing spaces are not highlighted correctly (only the initial token preceding the space is highlighted in SearchAutocompleteInput), and running the search results in "Nothing to show" instead of returning the matching expenses. Additionally, typing vendor: does not display any autocomplete suggestions for vendors from connected workspace policies, forcing the user to type vendor names manually without quotes.
What is the root cause of that problem?
Missing Vendor Autocomplete Suggestions:
In src/hooks/useAutocompleteSuggestions.ts, switch (autocompleteKey) provides autocomplete handlers for TAG, CATEGORY, CURRENCY, TAX_RATE, FROM, TO, STATUS, IN, ACTION, etc., but completely lacks a handler for CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR. When a user types vendor:, the hook returns an empty array, so no vendor suggestions appear.
Missing Multi-Word Continuation Detection for Vendor:
In src/libs/SearchAutocompleteUtils.ts, CONTINUATION_DETECTION_SEARCH_FILTER_KEYS contains [TO, FROM, ASSIGNEE, PAYER, PAID_BY, EXPORTER, ATTENDEE], but does not include CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR. When a user types a multi-word vendor name separated by a space (e.g. vendor:Admin Denis), the parser treats the trailing word as a free-text token. Because VENDOR is absent from CONTINUATION_DETECTION_SEARCH_FILTER_KEYS, useAutocompleteSuggestions does not bridge the space continuation, dropping autocomplete entirely.
Syntax Highlighting and Lexer Delimitation for Unquoted Values:
In src/libs/SearchParser/autocompleteParser.peggy and searchParser.peggy, unquoted filter values are parsed by alphanumeric = chars:(escapedChar / [^ ,\t\n\r\xA0])+, which delimits tokens by whitespace. In Expensify's Search syntax, values containing whitespace must be wrapped in double quotes (e.g. vendor:"A B"). When a user selects a suggestion from the autocomplete dropdown, SearchRouter.tsx automatically invokes sanitizeSearchValue(item.searchQuery), which wraps multi-word strings in double quotes. Because vendor autocomplete was not implemented, users were forced to type the vendor name manually without quotes. This caused autocompleteParser to highlight only the first word (e.g. "A" in "A B", leaving "B" unhighlighted) and caused searchParser to interpret the trailing words as disjoint keyword filters (vendor: "A" AND keyword: "B"), leading to zero matching search results.
Missing Live Markdown Shared Value for Vendor:
In src/components/Search/SearchAutocompleteInput.tsx, shared values are provisioned and synchronized on the live markdown runtime for categories, tags, currencies, logins, and exportedTo destinations, but no vendorSharedValue is provided to parseForLiveMarkdown for vendor name validation.
What changes do you think we should make in order to solve the problem?
In src/libs/SearchAutocompleteUtils.ts:
Add getAutocompleteVendors to extract unique vendor names across accessible policies (using getVendorFeaturePolicyIDs and getMatchingVendors from @libs/PolicyUtils):
In src/components/Search/SearchAutocompleteInput.tsx:
Subscribe to ONYXKEYS.COLLECTION.POLICY and provide vendorSharedValue via getAutocompleteVendors:
--- a/src/components/Search/SearchAutocompleteInput.tsx+++ b/src/components/Search/SearchAutocompleteInput.tsx@@ -16,7 +16,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
import {setSearchContext} from '@libs/actions/Search';
import scheduleOnLiveMarkdownRuntime from '@libs/scheduleOnLiveMarkdownRuntime';
-import {getAutocompleteCategories, getAutocompleteTags, parseForLiveMarkdown} from '@libs/SearchAutocompleteUtils';+import {getAutocompleteCategories, getAutocompleteTags, getAutocompleteVendors, parseForLiveMarkdown} from '@libs/SearchAutocompleteUtils';
import {expensifyLoginsSelector} from '@libs/UserUtils';
Pass vendorSharedValue into parseForLiveMarkdown and update filterOutRangesWithCorrectValue in SearchAutocompleteUtils.ts to validate against vendorList.get().includes(range.value) || range.value.length > 0.
When a user types vendor: or vendor:A, autocomplete presents A B. Upon selection, SearchRouter.tsx runs sanitizeSearchValue("A B"), automatically quoting it as vendor:"A B" . The entire vendor name is highlighted as a single live markdown range, and the parsed AST filter matches vendor: "A B", properly displaying all matching expenses.
What alternative solutions did you explore? (Optional)
Allowing unquoted multi-word strings directly in Peggy grammar:
Not recommended because whitespace is the canonical token delimiter across Expensify's search parser grammar. Changing alphanumeric to swallow spaces would introduce severe syntactic ambiguities with trailing operators, keywords, and subsequent filter keys. Relying on autocomplete selection with sanitizeSearchValue preserves 100% consistency with existing filters such as category:"Travel Meals", from:"John Doe", and merchant:"United Airlines".
What automated tests can you add to prevent this from re-occurring?
In tests/unit/hooks/useAutocompleteSuggestions.test.ts:
Add a unit test verifying that autocompleteQueryValue: 'vendor:' returns matching vendor suggestions from connected workspace policies.
Add a unit test verifying continuation detection for multi-word vendor names (e.g. vendor:Admin Denis), ensuring suggestions are returned even when spaces are present before quotes are applied.
In tests/unit/SearchAutocompleteUtilsTest.ts:
Add a unit test verifying getAutocompleteVendors extracts unique vendor names across policies.
Add a unit test asserting parseForLiveMarkdown correctly highlights multi-word quoted vendors (vendor:"A B").
Only MelvinBot's proposal counts here, since this issue never had the Help Wanted label.
Not a bug
I tested this with a QBO workspace (company card expenses exported as Credit card) and non-reimbursable expenses with synced vendors A A and Five Stars. Everything matches MelvinBot's root cause:
type:expense vendor:A A: only the first A is highlighted and nothing is returned.
type:expense vendor:"A A": the full name is highlighted and the matching expense is returned.
type:expense vendor:Five Stars: only Five is highlighted and nothing is returned.
type:expense vendor:"Five Stars": the full name is highlighted and the matching expense is returned.
A value without quotes ends at the first space (baseRules.peggy:221), so vendor:Five Stars searches vendor:Five plus the keyword Stars. The same is true for every free-text filter (merchant:, description:). Multi-word values need quotes.
The issue's colonless searches (vendor A B, vendor Admin Denis) aren't vendor filters at all. They're keyword searches, so nothing is highlighted and the server decides what matches. The test steps come from Tests step 6 of #104351 (type:expense vendor:<name>), which didn't say that multi-word names need quotes.
Recommendation
Close this as not a bug, and update the regression test case to quote multi-word vendor names, e.g. type:expense vendor:"A B".
MelvinBot's vendor: autocomplete idea would help users find the right syntax, but it's a new feature rather than a fix (merchant: has no autocomplete either). Up to you whether to track it separately.
Activity
applause-bot commentedon Oct 29, 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/d8eba1b8c483cf692fdae1f7eb9d1964794b7c8664a6436dad1b3942aa26e821
MelvinBot commentedon Oct 29, 2026
Proposal
What is the root cause of that problem?
This is mostly expected search syntax, plus one missing feature in the search box:
vendor:A B(step 3). An unquoted value ends at the first space. This is true for every filter, not onlyvendor(baseRules.peggy:221). The query becomesvendor:Aplus the keywordB, so only "A" is highlighted and nothing matches. Multi-word values must be quoted, for examplevendor:"A B". Merchant, category, and tag work the same way.vendor A Bandvendor Admin Denis(steps 4 and 5). Without a colon, these are plain keyword searches. The App sends the words to the server unchanged, and the server decides what matches. Nothing is highlighted because there is no filter.vendor:in the search box suggests no vendors. The suggestion switch handles tag and category, but has noVENDORcase (useAutocompleteSuggestions.ts:186-203). For other filters, picking a suggestion adds the quotes automatically (SearchRouter.tsx:476). For vendor, you have to type the quotes yourself, and the test step didn't include them.What changes do you think we should make in order to solve the problem?
VENDORcase touseAutocompleteSuggestions.ts. Fill it from the same synced vendor list that the Filters > Vendor picker uses. Selecting a vendor then insertsvendor:"A B"and highlights the full name.vendor:"<name>"for names that contain spaces.Steps 4 and 5 (keyword results) are decided by the server. If those results are wrong, an internal engineer needs to look at them.
What alternative solutions did you explore? (Optional)
Let
vendor:accept unquoted values that contain spaces. I rejected this because it would break the rule every other filter follows. It would also makevendor:A Bambiguous with a following keyword.Supporting evidence
baseRules.peggy:231-238.SearchAutocompleteUtils.ts:309-313.vendor:"Acme Tools":SearchAutocompleteUtilsTest.ts:228-235.SearchQueryUtils.ts:2016-2019.Possibly related: [$175] Filters - Vendor option is missing in filters
Next Steps for Contributor+ team:
To accept:
@MelvinBot implement [this](https://github.com/Expensify/App/issues/105375)to create a draft PR.To refine:
@MelvinBot <your feedback>To reject: Explain why you are rejecting Melvin's proposal.
view run
melvin-bot commentedon Oct 29, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @ikevin127 (
External)[-]Search-"type:expense vendor name", vendor name not highlighted and search result not correct[/-][+][$175] Search-"type:expense vendor name", vendor name not highlighted and search result not correct[/+]melvin-bot commentedon Oct 29, 2026
Job added to Upwork: https://www.upwork.com/jobs/~022115775834824322193
camesenin commentedon Oct 29, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
The reported searches do not highlight or return the vendor names as the tester expects. However, the report mixes explicit filter syntax (
vendor:A B) with plain text (vendor A B), so the expected behavior must be checked against the supported search syntax before classifying this as a code regression.Verdict: MelvinBot’s proposal is incomplete as a fix for the reported reproduction steps. No independently verified replacement patch is established.
What is the root cause of that problem?
The supplied proposal describes three distinct behaviors:
type:expense vendor:A BA, plus keywordBtype:expense vendor A Btype:expense vendor Admin DenisMelvin cites these implementation locations:
src/libs/SearchParser/baseRules.peggy:221,231–238: unquoted and quoted value boundaries.src/hooks/useAutocompleteSuggestions.ts:186–203: suggestion dispatch.src/components/Search/SearchRouter/SearchRouter.tsx:476: suggestion insertion.src/libs/SearchQueryUtils.ts:2016–2019: vendor query handling.These are references supplied by Melvin, not source locations independently verified during this audit. The pinned files and target issue could not be retrieved, no Expensify checkout exists in this workspace, and no parser, Jest, or browser reproduction was run.
Consequently:
What changes do you think we should make in order to solve the problem?
Do not approve an implementation from the current evidence. First establish whether the supported baseline,
type:expense vendor:"A B", highlights the complete name and returns the intended expense in the stated QBO configuration.Then use the smallest change supported by that result:
An autocomplete patch must account for vendor data arriving after the hook mounts, workspace changes, duplicate names across workspaces, empty results, and values containing punctuation or quotes. These are required verification cases; they are not proven failures in existing code.
No TypeScript diff is included because the actual types, helpers, dependencies, and insertion logic were unavailable. Inventing those details would fail the requirement for an exact, production-reviewable patch.
What alternative solutions did you explore? (Optional)
MelvinBot’s central coverage failure: adding suggestions only changes behavior when a user selects a suggestion. It does not change any of the three reported queries when typed and submitted unchanged. Updating the test to use quotes changes the reproduction procedure; it does not prove the original behavior was fixed.
Melvin’s syntax explanation may nevertheless be correct. Rewriting the parser to absorb spaces would introduce ambiguity between vendor values and subsequent keywords without an established syntax contract.
Likewise, adding a colon automatically to
vendor Admin Deniscould reinterpret legitimate keyword searches.The related vendor-filter issue documents earlier removal and restoration work. That warrants an overlap check; it does not establish duplication of this autocomplete issue.
A claim that this is “the only safe solution” is unsupported. Expensify’s contribution guidelines require reproduction before proposing a fix and meaningful differentiation from existing proposals.
What automated tests can you add to prevent this from re-occurring?
Once the source is available, add focused Jest coverage:
vendor:"A B"preserves one complete vendor value and creates no strayBkeyword.vendor:A Band colonless queries.A Bwith the caret inside an existing query; assert that the inserted value parses back to exactlyA Bwhile neighboring filters and keywords remain intact.Mocked Jest responses cannot establish backend result correctness. That requires a controlled reproduction with the two stated expenses and captured request/result evidence.
Execution status: none of these tests were run; no passing validation is claimed.
Contributor details
Your Expensify account email: [email protected]
Upwork Profile Link: https://www.upwork.com/freelancers/~01b60d704ba377be83
melvin-bot commentedon Oct 29, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
khizzcr7 commentedon Oct 29, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
Searching
type:expense vendor:A Bhighlights only "A" and returns nothing, and colonless searches liketype:expense vendor Admin Denishighlight nothing and return wrong results. The tester expects the vendor name to be highlighted like other filter values and the results to match the filtered expenses.What is the root cause of that problem?
Two distinct behaviors, one of which is a genuine App gap:
vendor:A Bparses as vendorAplus keywordB, so only "A" is highlighted and nothing matches both conditions. Multi-word vendor values must be quoted, e.g.vendor:"A B". Without a colon,vendor A Bandvendor Admin Denisare plain keyword searches, so nothing is highlighted and the server decides what matches.vendor:suggests no vendors. Verified against main source: the switch insrc/hooks/useAutocompleteSuggestions.tscovers TAG, CATEGORY, CURRENCY, TAX_RATE and user filters, but has no vendor case. So a user can never discover the correct quoted form from the search box, which is exactly why the tester typed the unquoted forms.What changes do you think we should make in order to solve the problem?
Add a vendor case to
useAutocompleteSuggestions.ts, mirroring the existing TAG/CATEGORY cases:alreadyAutocompletedKeysdedup the TAG case uses).sanitizeSearchValueinsrc/libs/SearchQueryUtils.tsalready wraps any value containing a space in quotes, so selecting "A B" insertsvendor:"A B", which parses as a single vendor value and highlights in full.What alternative solutions did you explore?
vendor:A Bambiguous with a vendor filter plus a keyword, and would change behavior for every filter.vendor: rejected, it would reinterpret legitimate keyword searches.What automated tests can you add to prevent this from re-occurring?
vendor:with a synced vendor list returns matching vendors; with no synced list returns an empty list.vendor:"A B"and reparsing yields exactly one vendor valueA B, with neighbouring filters intact.vendor:A Bstill parses as vendorAplus keywordB(documented behaviour, unchanged).sonofkratos92 commentedon Oct 29, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
When searching in
Spend > Expensesfor expenses with multi-word vendor names like"A B"or"Admin Denis":type:expense vendor:A Bonly highlightsAin the search input, shows no vendor autocomplete suggestions to select"A B", and returns no results (becauseAis parsed as the vendor filter value andBis parsed as a separate free-text keyword).type:expense vendor A Bortype:expense vendor Admin Deniswithout a colon runs a plain keyword search rather than avendor:filter.What is the root cause of that problem?
src/libs/SearchParser/baseRules.peggy:221), unquoted filter values terminate at whitespace, so multi-word filter values must be quoted (vendor:"A B"). When a user typesvendor:Aand then presses space followed byB(type:expense vendor:A B),defaultFilterinsrc/libs/SearchParser/autocompleteParser.peggy:39-75parsesvendor:AintorangesandfreeTextFilter(autocompleteParser.peggy:83) parsesBand resetsautocomplete = null.src/hooks/useAutocompleteSuggestions.tshas nocase CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR:branch, so typingvendor:never suggests synced workspace vendors (unlikecategory:,tag:, orexported-to:), which is what normally wraps multi-word values in quotes viasanitizeSearchValueinsrc/components/Search/SearchRouter/SearchRouter.tsx:480.VENDORcase is added touseAutocompleteSuggestions.tsalone,CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDORis also missing fromCONTINUATION_DETECTION_SEARCH_FILTER_KEYSinsrc/libs/SearchAutocompleteUtils.ts:683-691. WithoutVENDORinCONTINUATION_DETECTION_SEARCH_FILTER_KEYS(andmapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDORon each suggestion item):type:expense vendor:A Bortype:expense vendor:Admin Denis),parseForAutocompletereturnsautocomplete: null. BecauseuseAutocompleteSuggestions.ts:157-168only checksCONTINUATION_DETECTION_SEARCH_FILTER_KEYSwhen!autocomplete, the vendor suggestions disappear immediately after the space is typed.getTrimmedUserSearchQueryPreservingComma(src/libs/SearchAutocompleteUtils.ts:1045-1071) only trims back tovendor:(or the last comma) whenfieldKeyis inCONTINUATION_DETECTION_SEARCH_FILTER_KEYS; otherwise it falls back togetQueryWithoutAutocompletedPart(textInputValue), which returns the untrimmed string whenparsedQuery.autocompleteisnulland producestype:expense vendor:A B"A B".What changes do you think we should make in order to solve the problem?
src/libs/SearchAutocompleteUtils.ts, addCONST.SEARCH.SYNTAX_FILTER_KEYS.VENDORtoCONTINUATION_DETECTION_SEARCH_FILTER_KEYS:src/hooks/useAutocompleteSuggestions.ts, importusePermissionsfrom./usePermissionsandgetMatchingVendors, getVendorFeaturePolicyIDsfrom@libs/PolicyUtils, checkconst isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING);, and add theVENDORcase toswitch (autocompleteKey)using the same synced vendor source asVendorSelector.tsxwithmapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR:With both changes in place, typing
type:expense vendor:A Bortype:expense vendor:Admin Deniskeeps the matching vendor suggestion visible across spaces, and selecting it replaces the unquoted text aftervendor:withvendor:"A B"(orvendor:"Admin Denis"), highlighting the full vendor name and returning the matching expense.What alternative solutions did you explore? (Optional)
Changing the Peggy parser to allow unquoted spaces inside
vendor:values would makevendor:A Bambiguous with trailing search keywords and break consistency with other filters (merchant:,category:,tag:). AddingVENDORtouseAutocompleteSuggestionstogether withCONTINUATION_DETECTION_SEARCH_FILTER_KEYSpreserves the standard quoted syntax while supporting multi-word vendor autocomplete when typing spaces.apoorv-xs commentedon Oct 29, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
When typing a vendor filter in the global Search bar (such as
type:expense vendor:A Bortype:expense vendor Admin Denis), multi-word vendor names containing spaces are not highlighted correctly (only the initial token preceding the space is highlighted inSearchAutocompleteInput), and running the search results in "Nothing to show" instead of returning the matching expenses. Additionally, typingvendor:does not display any autocomplete suggestions for vendors from connected workspace policies, forcing the user to type vendor names manually without quotes.What is the root cause of that problem?
In
src/hooks/useAutocompleteSuggestions.ts,switch (autocompleteKey)provides autocomplete handlers forTAG,CATEGORY,CURRENCY,TAX_RATE,FROM,TO,STATUS,IN,ACTION, etc., but completely lacks a handler forCONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR. When a user typesvendor:, the hook returns an empty array, so no vendor suggestions appear.In
src/libs/SearchAutocompleteUtils.ts,CONTINUATION_DETECTION_SEARCH_FILTER_KEYScontains[TO, FROM, ASSIGNEE, PAYER, PAID_BY, EXPORTER, ATTENDEE], but does not includeCONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR. When a user types a multi-word vendor name separated by a space (e.g.vendor:Admin Denis), the parser treats the trailing word as a free-text token. BecauseVENDORis absent fromCONTINUATION_DETECTION_SEARCH_FILTER_KEYS,useAutocompleteSuggestionsdoes not bridge the space continuation, dropping autocomplete entirely.In
src/libs/SearchParser/autocompleteParser.peggyandsearchParser.peggy, unquoted filter values are parsed byalphanumeric = chars:(escapedChar / [^ ,\t\n\r\xA0])+, which delimits tokens by whitespace. In Expensify's Search syntax, values containing whitespace must be wrapped in double quotes (e.g.vendor:"A B"). When a user selects a suggestion from the autocomplete dropdown,SearchRouter.tsxautomatically invokessanitizeSearchValue(item.searchQuery), which wraps multi-word strings in double quotes. Because vendor autocomplete was not implemented, users were forced to type the vendor name manually without quotes. This causedautocompleteParserto highlight only the first word (e.g. "A" in "A B", leaving "B" unhighlighted) and causedsearchParserto interpret the trailing words as disjointkeywordfilters (vendor: "A"ANDkeyword: "B"), leading to zero matching search results.In
src/components/Search/SearchAutocompleteInput.tsx, shared values are provisioned and synchronized on the live markdown runtime for categories, tags, currencies, logins, and exportedTo destinations, but novendorSharedValueis provided toparseForLiveMarkdownfor vendor name validation.What changes do you think we should make in order to solve the problem?
In
src/libs/SearchAutocompleteUtils.ts:getAutocompleteVendorsto extract unique vendor names across accessible policies (usinggetVendorFeaturePolicyIDsandgetMatchingVendorsfrom@libs/PolicyUtils):CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDORtoCONTINUATION_DETECTION_SEARCH_FILTER_KEYS:In
src/hooks/useAutocompleteSuggestions.ts:CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDORcase touseAutocompleteSuggestions:In
src/components/Search/SearchAutocompleteInput.tsx:ONYXKEYS.COLLECTION.POLICYand providevendorSharedValueviagetAutocompleteVendors:vendorSharedValueintoparseForLiveMarkdownand updatefilterOutRangesWithCorrectValueinSearchAutocompleteUtils.tsto validate againstvendorList.get().includes(range.value) || range.value.length > 0.When a user types
vendor:orvendor:A, autocomplete presentsA B. Upon selection,SearchRouter.tsxrunssanitizeSearchValue("A B"), automatically quoting it asvendor:"A B". The entire vendor name is highlighted as a single live markdown range, and the parsed AST filter matchesvendor: "A B", properly displaying all matching expenses.What alternative solutions did you explore? (Optional)
Allowing unquoted multi-word strings directly in Peggy grammar:
Not recommended because whitespace is the canonical token delimiter across Expensify's search parser grammar. Changing
alphanumericto swallow spaces would introduce severe syntactic ambiguities with trailing operators, keywords, and subsequent filter keys. Relying on autocomplete selection withsanitizeSearchValuepreserves 100% consistency with existing filters such ascategory:"Travel Meals",from:"John Doe", andmerchant:"United Airlines".What automated tests can you add to prevent this from re-occurring?
tests/unit/hooks/useAutocompleteSuggestions.test.ts:autocompleteQueryValue: 'vendor:'returns matching vendor suggestions from connected workspace policies.vendor:Admin Denis), ensuring suggestions are returned even when spaces are present before quotes are applied.tests/unit/SearchAutocompleteUtilsTest.ts:getAutocompleteVendorsextracts unique vendor names across policies.parseForLiveMarkdowncorrectly highlights multi-word quoted vendors (vendor:"A B").Contributor details
Your Expensify account email: [email protected]
Upwork Profile Link: https://www.upwork.com/freelancers/~01f7d7991785f2ee01
melvin-bot commentedon Oct 29, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
ikevin127 commentedon Oct 29, 2026
Proposals review
Only MelvinBot's proposal counts here, since this issue never had the
Help Wantedlabel.Not a bug
I tested this with a QBO workspace (company card expenses exported as Credit card) and non-reimbursable expenses with synced vendors
A AandFive Stars. Everything matches MelvinBot's root cause:type:expense vendor:A A: only the firstAis highlighted and nothing is returned.type:expense vendor:"A A": the full name is highlighted and the matching expense is returned.type:expense vendor:Five Stars: onlyFiveis highlighted and nothing is returned.type:expense vendor:"Five Stars": the full name is highlighted and the matching expense is returned.A value without quotes ends at the first space (
baseRules.peggy:221), sovendor:Five Starssearchesvendor:Fiveplus the keywordStars. The same is true for every free-text filter (merchant:,description:). Multi-word values need quotes.The issue's colonless searches (
vendor A B,vendor Admin Denis) aren't vendor filters at all. They're keyword searches, so nothing is highlighted and the server decides what matches. The test steps come from Tests step 6 of #104351 (type:expense vendor:<name>), which didn't say that multi-word names need quotes.Recommendation
Close this as not a bug, and update the regression test case to quote multi-word vendor names, e.g.
type:expense vendor:"A B".MelvinBot's
vendor:autocomplete idea would help users find the right syntax, but it's a new feature rather than a fix (merchant:has no autocomplete either). Up to you whether to track it separately.🎀👀🎀 C+ reviewed
melvin-bot commentedon Oct 29, 2026
Triggered auto assignment to @jasperhuangg, see https://stackoverflow.com/c/expensify/questions/7972 for more details.