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] [Sentry: APP-DRT] Web: category picker crashes when a category has no name #104745
sortCategories expects every entry in the policy categories to have a string name. At least one entry has no name (for example an optimistic or partial category from Onyx), so processCategoryNameSegments calls split on undefined and the category picker crashes during render.
Reproduction
Unknown. See the Sentry events linked from the Sentry issue.
changed the title [-][Sentry: APP-DRT] Web: category picker crashes when a category has no name[/-][+][$175] [Sentry: APP-DRT] Web: category picker crashes when a category has no name[/+]on Oct 22, 2026
CategoryPicker passes the policy categories from Onyx straight into sortCategories. That function calls processCategoryNameSegments(category.name) on every entry and never checks that name exists. One entry without a name crashes the picker during render.
Nameless entries can appear because many category actions merge partial objects keyed by category name, with no name field (for example {pendingAction, pendingFields, errors}). If that key no longer exists when the merge lands, Onyx creates a new "ghost" entry with no name. This can happen when the server has already renamed or deleted the category.
The crash path is confirmed in code. I couldn't confirm which action creates the ghost entry in production.
Likely sources of nameless entries, in Category.ts:
renamePolicyCategory success data merges {[newName]: {pendingAction, pendingFields}}: L944-L955
deleteWorkspaceCategories optimistic and failure data: L1357-L1363
Per-field setters (enabled, max amount, receipts required, and others) whose success and failure data omit name.
Not the cause: the Search snapshot (it doesn't hold policyCategories_), recently used categories, and the selected category. None of these reach sortCategories.
Git history shows no May 2026 code change that introduced this. The first-seen date likely reflects new data, not new code.
What changes do you think we should make in order to solve the problem?
In sortCategories, skip any category whose name is not a string before sorting. This protects both callers of sortCategories. Ghost entries have no useful data, so the list doesn't lose anything. A similar !!tagList.name filter already exists in src/libs/actions/Policy/Tag.ts.
Add a unit test for getCategoryListSections with a category that has no name.
What alternative solutions did you explore? (Optional)
Make processCategoryNameSegments return [] for a missing name. This is a wider safety net, but it hides bad data from other callers.
Root-cause hardening, as a separate change: include name in the per-key success and failure data in Category.ts. This doesn't cover a backend that sends partial categories, so the render guard is still needed.
Next Steps for Contributor+ team: To accept:@MelvinBot implement [this](https://github.com/Expensify/App/issues/104745) to create a draft PR. To refine:@MelvinBot <your feedback> To reject: Explain why you are rejecting Melvin's proposal.
Please re-state the problem that we are trying to solve in this issue.
On web, opening the category picker (for example from /search/view/:reportID) throws TypeError: Cannot read properties of undefined (reading 'split'). The error is fatal and blocks the app. It happens when one entry in the policy categories Onyx collection has no name. CategoryPicker should not crash because of malformed or partial category data.
What is the root cause of that problem?
CategoryPicker passes the policyCategories Onyx value straight into getCategoryListSections, which calls sortCategories. sortCategories calls processCategoryNameSegments(category.name) for every entry, and that calls categoryName.split(CONST.PARENT_CHILD_SEPARATOR). Nothing checks that name is a non-empty string. The existing if (name) check later in getCategoryListSections runs after the crash point.
Nameless entries ("ghost" categories) most likely come from Onyx merges keyed by category name that carry only metadata, such as {pendingAction, pendingFields, errors}. Examples are the success and failure data in renamePolicyCategory, deleteWorkspaceCategories, and the per-field setters in Category.ts. If the key no longer exists when the merge lands (for example, the server already renamed or deleted it), Onyx creates a new object without name. A backend response with partial categories would have the same effect. I couldn't confirm which of these produces the ghost entry in production, but the crash path is clear and the picker has to tolerate this data either way.
What changes do you think we should make in order to solve the problem?
Add a shared guard in src/libs/CategoryOptionListUtils.ts. Drop entries without a usable name before any name-based processing.
functionhasValidCategoryName(category: PolicyCategory|undefined): category is PolicyCategory{returntypeofcategory?.name==='string'&&category.name.length>0;}
Apply the guard in sortCategories, which is the actual crash site and has more than one caller:
functionsortCategories(categories: Record<string,Category>,localeCompare: LocaleContextProps['localeCompare']): Category[]{constvalidCategories=Object.values(categories??{}).filter(hasValidCategoryName);// ...build the hierarchy and sort from `validCategories` instead of Object.values(categories)}
Apply the guard at the top of getCategoryListSections so the other branches that read category.name are also safe. These are the search, selected-options, enabled-filter, and recently-used branches:
Then use validCategories or enabledCategories throughout the function instead of the raw categories.
Keep processCategoryNameSegments strict. It continues to take a string. The data is cleaned at the boundary, so bad data isn't hidden from other callers.
Follow-up hardening (optional, separate PR). In src/libs/actions/Policy/Category.ts, include name in the per-key optimistic, success, and failure data (rename, delete, and enabled, max amount, and receipts-required setters). This stops ghost entries from being created locally. The render guard is still needed for backend-originated partial data.
Add unit tests in tests/unit/CategoryOptionListUtilsTest.ts:
getCategoryListSections with a categories map containing { ghost: { pendingAction: 'update' } } (no name) alongside valid ones. It should not throw, and the result should contain only the valid categories.
The same case with a non-empty searchValue, with selectedOptions, and with recentlyUsedCategories.
sortCategories with a nameless entry. It should not throw and should omit that entry.
What alternative solutions did you explore? (Optional)
Make processCategoryNameSegments return [] for a missing name. This is a smaller change, but it only fixes one function. The nameless entry would still reach other code that reads category.name, and it could produce blank rows in the list. It also hides bad data from every other caller.
Filter only inside sortCategories. This fixes the reported stack trace but leaves other category.name accesses in getCategoryListSections unprotected. Guarding at both levels is cheap.
Filter with an Onyx selector in CategoryPicker. This only protects one component, and other callers of getCategoryListSections and sortCategories would remain exposed.
Fix only the producers in Category.ts. This doesn't cover data already stored in users' Onyx or partial backend data, so a render-side guard is still required.
Testing
Run the new unit tests and the existing CategoryOptionListUtilsTest, and confirm they pass.
Manual reproduction:
Open a workspace report or expense that has categories, and use dev tools to merge a ghost entry into policyCategories_<policyID>, for example { "Ghost": { pendingAction: "update" } }.
Open the category picker, including through the Search report view /search/view/:reportID.
Before the fix, the picker crashes with the split error. After the fix, it renders only the valid categories.
Type in the search box and select a category to confirm the search and selection branches also work.
Regression check: a policy with normal nested categories (Parent:Child) still renders the same hierarchy, order, and selected state.
Confirm there are no crashes or console errors in the picker on web, and spot-check desktop and mobile.
Please re-state the problem that we are trying to solve in this issue.
On Web (and other platforms), when opening the category picker (such as from /search/view/:reportID), the app crashes fatally with TypeError: Cannot read properties of undefined (reading 'split').
What is the root cause of that problem?
In src/libs/CategoryOptionListUtils.ts:
sortCategories (called directly by getCategoryListSections:111) iterates over all entries of the categories dictionary and attempts to sort them:
If Onyx contains any partial, optimistic, or deleted category entry lacking a name attribute (e.g. {pendingAction: 'update'} or {errors: ...} created by partial merges), category.name is undefined. Calling .split() on undefined causes a fatal runtime crash.
What changes do you think we should make in order to solve the problem?
In src/libs/CategoryOptionListUtils.ts:
Filter out entries with invalid or missing name at the entry point of sortCategories.
Also ensure getCategoryListSections uses guarded category entries so secondary lookups (enabledCategories, search, selectedOptions) never encounter nameless entries.
--- a/src/libs/CategoryOptionListUtils.ts+++ b/src/libs/CategoryOptionListUtils.ts@@ -260,7 +260,10 @@ function buildHierarchy(categories: Category[]) {
}
function sortCategories(categories: Record<string, Category>, localeCompare: LocaleContextProps['localeCompare']): Category[] {
- const sortedCategories = Object.values(categories).sort((a, b) => localeCompare(a.name, b.name));+ const validCategories = Object.values(categories ?? {}).filter(+ (category): category is Category & {name: string} => typeof category?.name === 'string' && category.name.trim().length > 0,+ );+ const sortedCategories = validCategories.sort((a, b) => localeCompare(a.name, b.name));
// An object that respects nesting of categories. Also, can contain only uniq categories.
const hierarchy: Hierarchy = {};
Key Advantages:
Direct crash site protection: Defends both localeCompare(a.name, b.name) (which also throws or fails when name is undefined) and processCategoryNameSegments(category.name).
Defensive data boundary: Prevents ghost/malformed Onyx records from corrupting the category hierarchy structure.
Zero side-effects: Valid categories continue sorting and nesting as expected (Parent: Child).
What alternative solutions did you explore? (Optional)
Adding a fallback in processCategoryNameSegments(categoryName: string = ''):
Rejected. While this prevents the .split() crash inside that single helper, it allows invalid empty items into the hierarchy, which can lead to empty list items in the UI or undefined keys in localeCompare. Sanitizing in sortCategories is cleaner and safer.
What automated tests can you add to prevent this from re-occurring?
In tests/unit/CategoryOptionListUtilsTest.ts:
Add a test case for sortCategories passing a categories dictionary containing a nameless entry:
it('should ignore categories without a valid name during sorting and hierarchy creation',()=>{constmockCategories={ValidCategory: {name: 'ValidCategory',enabled: true},GhostCategory: {pendingAction: 'update',enabled: false}asunknownasCategory,};constresult=sortCategories(mockCategories,(a,b)=>a.localeCompare(b));expect(result).toHaveLength(1);expect(result[0].name).toBe('ValidCategory');});
Please re-state the problem that we are trying to solve in this issue.
The category picker crashes when rendering policy categories if any category record lacks a valid string name.
What is the root cause of that problem?
In src/libs/CategoryOptionListUtils.ts, sortCategories loops over categories and calls processCategoryNameSegments(category.name). In src/libs/CategoryUtils.ts line 234, processCategoryNameSegments expects categoryName to be a string and directly invokes categoryName.split(CONST.PARENT_CHILD_SEPARATOR) without verifying if categoryName is defined. When Onyx contains a partial or malformed category entry where category.name is undefined, split throws an unhandled TypeError: Cannot read properties of undefined (reading 'split').
What changes do you think we should make in order to solve the problem?
In src/libs/CategoryUtils.ts:
In processCategoryNameSegments, guard against missing or non-string inputs by defaulting categoryName or returning an empty array immediately when !categoryName or typeof categoryName !== 'string'.
In src/libs/CategoryOptionListUtils.ts:
In getCategoryListSections, sanitize the category list input before passing it to sortCategories by filtering out entries without a valid name (e.g., Boolean(category?.name)).
Alternatively or companion to the above, inside sortCategories, verify category?.name before calling processCategoryNameSegments(category.name) so sorting comparator logic handles nameless records defensively.
What alternative solutions did you explore? (Optional)
I considered filtering nameless categories exclusively within sortCategories. However, guarding only inside sortCategories leaves other consumers of raw Onyx policyCategories (such as direct callers of processCategoryNameSegments across CategoryUtils.ts) vulnerable to the exact same crash when encountering unexpected ghost entries. Addressing the issue by sanitizing entries at the collection boundary in getCategoryListSections while also adding a defensive early return in processCategoryNameSegments provides complete defense without breaking backwards compatibility.
Contributor details
Your Expensify account email: [email protected]
Upwork Profile Link: Will provide shortly (currently encountering temporary rate limit on Upwork)
Proposal
Please re-state the problem that we are trying to solve in this issue.
On Web, opening the Category Picker can trigger a fatal crash: TypeError: Cannot read properties of undefined (reading 'split') in processCategoryNameSegments when a policy category entry in Onyx does not have a valid name string (e.g. corrupted, pending delete, or empty optimistic record).
What is the root cause of that problem?
In src/libs/CategoryOptionListUtils.ts:259-281, sortCategories() converts categories to an array via Object.values(categories) and assumes every entry has a valid string name:
If any category record in policyCategories_<policyID> lacks a name property (or name is undefined), sortCategories passes undefined to localeCompare and processCategoryNameSegments.
In src/libs/CategoryUtils.ts:234, processCategoryNameSegments unconditionally calls:
which throws TypeError: Cannot read properties of undefined (reading 'split').
What changes do you think we should make in order to solve the problem?
In src/libs/CategoryOptionListUtils.ts (sortCategories):
Filter for valid category records with non-empty string names before sorting and building the hierarchy tree:
--- a/src/libs/CategoryOptionListUtils.ts+++ b/src/libs/CategoryOptionListUtils.ts@@ -258,7 +258,8 @@ function getCategoryOptionTree(
function sortCategories(categories: Record<string, Category>, localeCompare: LocaleContextProps['localeCompare']): Category[] {
// Sorts categories alphabetically by name.
- const sortedCategories = Object.values(categories).sort((a, b) => localeCompare(a.name, b.name));+ const validCategories = Object.values(categories ?? {}).filter((category): category is Category & {name: string} => typeof category?.name === 'string' && category.name.trim() !== '');+ const sortedCategories = validCategories.sort((a, b) => localeCompare(a.name, b.name));
// An object that respects nesting of categories. Also, can contain only uniq categories.
const hierarchy: Hierarchy = {};
In src/libs/CategoryUtils.ts (processCategoryNameSegments):
Add a defensive falsy guard so the function safely returns an empty array if passed undefined, null, or an empty string:
What alternative solutions did you explore? (Optional)
Only adding the guard in processCategoryNameSegments was explored, but without filtering in sortCategories, localeCompare(a.name, b.name) would still receive undefined, which can cause sorting inconsistencies. Filtering in sortCategories guarantees clean data throughout the hierarchy builder.
Testing
Unit Tests:
In tests/unit/CategoryOptionListUtilsTest.ts, test sortCategories with a dictionary containing a category with name: undefined or missing name. Assert that it does not throw and returns sorted valid categories.
In tests/unit/CategoryUtilsTest.ts, test processCategoryNameSegments('') and processCategoryNameSegments(undefined as unknown as string) to confirm it returns [] without error.
Manual Testing:
Open a workspace, navigate to Categories, and open Category Picker. Verify categories render and sort properly.
Activity
melvin-bot commentedon Oct 22, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @mkhutornyi (
External)[-][Sentry: APP-DRT] Web: category picker crashes when a category has no name[/-][+][$175] [Sentry: APP-DRT] Web: category picker crashes when a category has no name[/+]melvin-bot commentedon Oct 22, 2026
Job added to Upwork: https://www.upwork.com/jobs/~022113270952359253686
MelvinBot commentedon Oct 22, 2026
Proposal
What is the root cause of that problem?
CategoryPickerpasses the policy categories from Onyx straight intosortCategories. That function callsprocessCategoryNameSegments(category.name)on every entry and never checks thatnameexists. One entry without anamecrashes the picker during render.Nameless entries can appear because many category actions merge partial objects keyed by category name, with no
namefield (for example{pendingAction, pendingFields, errors}). If that key no longer exists when the merge lands, Onyx creates a new "ghost" entry with noname. This can happen when the server has already renamed or deleted the category.The crash path is confirmed in code. I couldn't confirm which action creates the ghost entry in production.
Code references
if (name)check at line 299 runs too late.renamePolicyCategorysuccess data merges{[newName]: {pendingAction, pendingFields}}: L944-L955deleteWorkspaceCategoriesoptimistic and failure data: L1357-L1363name.policyCategories_), recently used categories, and the selected category. None of these reachsortCategories.What changes do you think we should make in order to solve the problem?
sortCategories, skip any category whosenameis not a string before sorting. This protects both callers ofsortCategories. Ghost entries have no useful data, so the list doesn't lose anything. A similar!!tagList.namefilter already exists insrc/libs/actions/Policy/Tag.ts.getCategoryListSectionswith a category that has noname.What alternative solutions did you explore? (Optional)
processCategoryNameSegmentsreturn[]for a missing name. This is a wider safety net, but it hides bad data from other callers.namein the per-key success and failure data inCategory.ts. This doesn't cover a backend that sends partial categories, so the render guard is still needed.Next Steps for Contributor+ team:
To accept:
@MelvinBot implement [this](https://github.com/Expensify/App/issues/104745)to create a draft PR.To refine:
@MelvinBot <your feedback>To reject: Explain why you are rejecting Melvin's proposal.
view run
Abdallah-1551 commentedon Oct 22, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
On web, opening the category picker (for example from
/search/view/:reportID) throwsTypeError: Cannot read properties of undefined (reading 'split'). The error is fatal and blocks the app. It happens when one entry in the policy categories Onyx collection has noname.CategoryPickershould not crash because of malformed or partial category data.What is the root cause of that problem?
CategoryPickerpasses thepolicyCategoriesOnyx value straight intogetCategoryListSections, which callssortCategories.sortCategoriescallsprocessCategoryNameSegments(category.name)for every entry, and that callscategoryName.split(CONST.PARENT_CHILD_SEPARATOR). Nothing checks thatnameis a non-empty string. The existingif (name)check later ingetCategoryListSectionsruns after the crash point.Nameless entries ("ghost" categories) most likely come from Onyx merges keyed by category name that carry only metadata, such as
{pendingAction, pendingFields, errors}. Examples are the success and failure data inrenamePolicyCategory,deleteWorkspaceCategories, and the per-field setters inCategory.ts. If the key no longer exists when the merge lands (for example, the server already renamed or deleted it), Onyx creates a new object withoutname. A backend response with partial categories would have the same effect. I couldn't confirm which of these produces the ghost entry in production, but the crash path is clear and the picker has to tolerate this data either way.What changes do you think we should make in order to solve the problem?
src/libs/CategoryOptionListUtils.ts. Drop entries without a usablenamebefore any name-based processing.sortCategories, which is the actual crash site and has more than one caller:getCategoryListSectionsso the other branches that readcategory.nameare also safe. These are the search, selected-options, enabled-filter, and recently-used branches:Then use
validCategoriesorenabledCategoriesthroughout the function instead of the rawcategories.Keep
processCategoryNameSegmentsstrict. It continues to take astring. The data is cleaned at the boundary, so bad data isn't hidden from other callers.Follow-up hardening (optional, separate PR). In
src/libs/actions/Policy/Category.ts, includenamein the per-key optimistic, success, and failure data (rename, delete, and enabled, max amount, and receipts-required setters). This stops ghost entries from being created locally. The render guard is still needed for backend-originated partial data.Add unit tests in
tests/unit/CategoryOptionListUtilsTest.ts:getCategoryListSectionswith a categories map containing{ ghost: { pendingAction: 'update' } }(noname) alongside valid ones. It should not throw, and the result should contain only the valid categories.searchValue, withselectedOptions, and withrecentlyUsedCategories.sortCategorieswith a nameless entry. It should not throw and should omit that entry.What alternative solutions did you explore? (Optional)
processCategoryNameSegmentsreturn[]for a missing name. This is a smaller change, but it only fixes one function. The nameless entry would still reach other code that readscategory.name, and it could produce blank rows in the list. It also hides bad data from every other caller.sortCategories. This fixes the reported stack trace but leaves othercategory.nameaccesses ingetCategoryListSectionsunprotected. Guarding at both levels is cheap.CategoryPicker. This only protects one component, and other callers ofgetCategoryListSectionsandsortCategorieswould remain exposed.Category.ts. This doesn't cover data already stored in users' Onyx or partial backend data, so a render-side guard is still required.Testing
CategoryOptionListUtilsTest, and confirm they pass.policyCategories_<policyID>, for example{ "Ghost": { pendingAction: "update" } }./search/view/:reportID.spliterror. After the fix, it renders only the valid categories.Parent:Child) still renders the same hierarchy, order, and selected state.magomedta commentedon Oct 22, 2026
Contributor details
Your Expensify account email: [email protected]
Upwork Profile Link: https://www.upwork.com/freelancers/~01777d047a06f0e470
Proposal
Please re-state the problem that we are trying to solve in this issue.
On Web (and other platforms), when opening the category picker (such as from
/search/view/:reportID), the app crashes fatally withTypeError: Cannot read properties of undefined (reading 'split').What is the root cause of that problem?
In
src/libs/CategoryOptionListUtils.ts:sortCategories(called directly bygetCategoryListSections:111) iterates over all entries of thecategoriesdictionary and attempts to sort them:sortedCategoriesat line 281:category.namedirectly intoprocessCategoryNameSegmentsinsrc/libs/CategoryUtils.ts:234:nameattribute (e.g.{pendingAction: 'update'}or{errors: ...}created by partial merges),category.nameisundefined. Calling.split()onundefinedcauses a fatal runtime crash.What changes do you think we should make in order to solve the problem?
In
src/libs/CategoryOptionListUtils.ts:nameat the entry point ofsortCategories.getCategoryListSectionsuses guarded category entries so secondary lookups (enabledCategories,search,selectedOptions) never encounter nameless entries.Key Advantages:
localeCompare(a.name, b.name)(which also throws or fails whennameis undefined) andprocessCategoryNameSegments(category.name).Parent: Child).What alternative solutions did you explore? (Optional)
processCategoryNameSegments(categoryName: string = ''):Rejected. While this prevents the
.split()crash inside that single helper, it allows invalid empty items into the hierarchy, which can lead to empty list items in the UI or undefined keys inlocaleCompare. Sanitizing insortCategoriesis cleaner and safer.What automated tests can you add to prevent this from re-occurring?
In
tests/unit/CategoryOptionListUtilsTest.ts:sortCategoriespassing a categories dictionary containing a nameless entry:melvin-bot commentedon Oct 22, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
taieddie commentedon Oct 22, 2026
Contributor details
Your Expensify account email: [email protected]
Upwork Profile Link: https://www.upwork.com/freelancers/~01af851c9a7f771775
Proposal
Please re-state the problem that we are trying to solve in this issue.
The category picker crashes when rendering policy categories if any category record lacks a valid string name.
What is the root cause of that problem?
In
src/libs/CategoryOptionListUtils.ts,sortCategoriesloops overcategoriesand callsprocessCategoryNameSegments(category.name). Insrc/libs/CategoryUtils.tsline 234,processCategoryNameSegmentsexpectscategoryNameto be a string and directly invokescategoryName.split(CONST.PARENT_CHILD_SEPARATOR)without verifying ifcategoryNameis defined. When Onyx contains a partial or malformed category entry wherecategory.nameis undefined,splitthrows an unhandledTypeError: Cannot read properties of undefined (reading 'split').What changes do you think we should make in order to solve the problem?
In
src/libs/CategoryUtils.ts:processCategoryNameSegments, guard against missing or non-string inputs by defaultingcategoryNameor returning an empty array immediately when!categoryNameortypeof categoryName !== 'string'.In
src/libs/CategoryOptionListUtils.ts:getCategoryListSections, sanitize the category list input before passing it tosortCategoriesby filtering out entries without a validname(e.g.,Boolean(category?.name)).sortCategories, verifycategory?.namebefore callingprocessCategoryNameSegments(category.name)so sorting comparator logic handles nameless records defensively.What alternative solutions did you explore? (Optional)
I considered filtering nameless categories exclusively within
sortCategories. However, guarding only insidesortCategoriesleaves other consumers of raw OnyxpolicyCategories(such as direct callers ofprocessCategoryNameSegmentsacrossCategoryUtils.ts) vulnerable to the exact same crash when encountering unexpected ghost entries. Addressing the issue by sanitizing entries at the collection boundary ingetCategoryListSectionswhile also adding a defensive early return inprocessCategoryNameSegmentsprovides complete defense without breaking backwards compatibility.melvin-bot commentedon Oct 22, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
HamzaKhanBUIC commentedon Oct 22, 2026
Contributor details
Your Expensify account email: [email protected]
Upwork Profile Link: Will provide shortly (currently encountering temporary rate limit on Upwork)
Proposal
Please re-state the problem that we are trying to solve in this issue.
On Web, opening the Category Picker can trigger a fatal crash:
TypeError: Cannot read properties of undefined (reading 'split')inprocessCategoryNameSegmentswhen a policy category entry in Onyx does not have a validnamestring (e.g. corrupted, pending delete, or empty optimistic record).What is the root cause of that problem?
src/libs/CategoryOptionListUtils.ts:259-281,sortCategories()convertscategoriesto an array viaObject.values(categories)and assumes every entry has a valid stringname:policyCategories_<policyID>lacks anameproperty (ornameis undefined),sortCategoriespassesundefinedtolocaleCompareandprocessCategoryNameSegments.src/libs/CategoryUtils.ts:234,processCategoryNameSegmentsunconditionally calls:TypeError: Cannot read properties of undefined (reading 'split').What changes do you think we should make in order to solve the problem?
In
src/libs/CategoryOptionListUtils.ts(sortCategories):Filter for valid category records with non-empty string names before sorting and building the hierarchy tree:
In
src/libs/CategoryUtils.ts(processCategoryNameSegments):Add a defensive falsy guard so the function safely returns an empty array if passed
undefined,null, or an empty string:What alternative solutions did you explore? (Optional)
Only adding the guard in
processCategoryNameSegmentswas explored, but without filtering insortCategories,localeCompare(a.name, b.name)would still receiveundefined, which can cause sorting inconsistencies. Filtering insortCategoriesguarantees clean data throughout the hierarchy builder.Testing
tests/unit/CategoryOptionListUtilsTest.ts, testsortCategorieswith a dictionary containing a category withname: undefinedor missingname. Assert that it does not throw and returns sorted valid categories.tests/unit/CategoryUtilsTest.ts, testprocessCategoryNameSegments('')andprocessCategoryNameSegments(undefined as unknown as string)to confirm it returns[]without error.melvin-bot commentedon Oct 22, 2026
HamzaKhanBUIC commentedon Oct 22, 2026
Contributor details
Your Expensify account email: [email protected]
Upwork Profile Link: https://www.upwork.com/freelancers/hamzakhanbuic
melvin-bot commentedon Oct 22, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
HamzaKhanBUIC commentedon Oct 22, 2026
Contributor details
Your Expensify account email: [email protected]
Upwork Profile Link: https://www.upwork.com/freelancers/~015055563b6090af39
melvin-bot commentedon Oct 22, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!