Repository navigation
HybridApp Android crash: getActivePolicy() returns null in SlidingMenuController Trips handler #82550
Description
Crash Description
On HybridApp Android, a fatal RuntimeException occurs in SlidingMenuController.js when the user navigates to the Trips page. The crash is caused by calling .getID() on a null return value from getActivePolicy().
Crash location: Mobile-Expensify/app/Controllers/SlidingMenuController.js line 397:
policyID: self.app.getActivePolicy().getID()Root Cause Analysis
This is inside the TRIPS page handler, which first checks self.app.isTravelEnabled() (line 395). If that returns true, it proceeds to call self.app.getActivePolicy().getID() — but getActivePolicy() can return null.
Why it returns null: In Mobile-Expensify/app/expensify.js (line 6077), getActivePolicy() returns null when no valid policy is found, and also triggers a sign-out:
if (!_.isPolicy(policy)) {
yaplShowGrowl('Something went wrong, please sign in and try again');
this.signOut();
return null;
}The race condition: isTravelEnabled() calls getActivePolicy() internally (line 7707) and succeeds. But by the time the code calls getActivePolicy() again on line 397, the policy may have been invalidated (e.g., sign-out started, or policy data cleared), causing null to be returned and .getID() to crash with a TypeError: Cannot read properties of null.
Proposed Fix
Add a null guard before calling .getID(), or cache the activePolicy result from the isTravelEnabled() check:
if (pageName === SlidingMenuController.PAGES.TRIPS) {
var activePolicy = self.app.getActivePolicy();
if (activePolicy && self.app.isTravelEnabled()) {
API.Travel_GenerateSpotnanaToken({
policyID: activePolicy.getID()
})
// ... rest of handler
}
}This avoids the double call to getActivePolicy() and eliminates the window for the race condition.
Related Issues
- Android hasNonCashCards HybridApp crash in Settings page #69370 — Same
getActivePolicy()null pattern but forhasNonCashCardsin SettingsController (closed) - HybridApp crashes are spiking! #56252 — SlidingMenuController crash spike (closed)
Issue Owner
Current Issue Owner: @QichenZhuMetadata
Metadata
Labels
Type
Projects
- StatusShow more project fieldsSUBISSUE
Activity
melvin-bot commentedon Feb 16, 2026
Triggered auto assignment to @greg-schroeder (
Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.melvin-bot commentedon Feb 16, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @Ollyws (
External)melvin-bot commentedon Feb 16, 2026
Unable to auto-create job on Upwork. The BZ team member should create it manually for this issue.
MelvinBot commentedon Feb 18, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
On HybridApp Android, a fatal
RuntimeExceptionoccurs when the user taps any row in the sliding menu (not just Trips). The crash is caused by calling.getID()on anullreturn value fromgetActivePolicy()inSlidingMenuController.js. ThegetActivePolicy()call is at the top of theonRowTappedCallbackshandler — before any page-specific branching — so it crashes regardless of which menu item is tapped whenevergetActivePolicy()returnsnull.What is the root cause of that problem?
In
_viewSetOnRowTappedCallback(Mobile-Expensify/app/Controllers/SlidingMenuController.js), the very first line of the callback unconditionally callsself.app.getActivePolicy().getID()with no null guard:getActivePolicy()(Mobile-Expensify/app/expensify.js:6076) explicitly returnsnullwhen no valid policy is found and also triggersthis.signOut()as a side effect. When the user taps a menu item while no valid policy exists (e.g., during app restore, before policies fully load, or during sign-out),.getID()is called onnulland the app crashes.There is a secondary unguarded call site:
isTravelEnabled()(Mobile-Expensify/app/expensify.js:7706) also callsgetActivePolicy()and immediately accessesactivePolicy.getTravelSettings()andactivePolicy.isPolicyProvisioned()without null checks, which would crash ifgetActivePolicy()returns null there.Note: The issue description frames this as a race condition between two sequential
getActivePolicy()calls. While there technically are two calls (one at the top of the handler, one insideisTravelEnabled()), the primary crash happens at the very first call — before any TRIPS-specific code runs. It's a missing null guard, not a race between the two calls.What changes do you think we should make in order to solve the problem?
Two changes in
Mobile-Expensify:SlidingMenuController.js— Move theactivePolicyIDassignment inside the TRIPS branch (since only the TRIPS path uses it), and add a null guard following the established codebase pattern:expensify.js— Add a null guard inisTravelEnabled()to returnfalseifgetActivePolicy()returns null:Both changes follow the established pattern used in
SettingsController.updateListItems(),CreateExpenseMenuController, andDropDownMenuControllerwhere the result ofgetActivePolicy()is stored in a variable and checked with_.isPolicy()before use.What alternative solutions did you explore? (Optional)
An alternative would be to make
getActivePolicy()itself never return null (e.g., return a default/empty policy object). However, this would mask a legitimate error state and the existingsignOut()side effect is intentional. The null guard approach is consistent with how this has been fixed elsewhere in the codebase (PR #13663 for #69370).Next Steps for Contributor+ team: Reply with
@MelvinBot implement thisto create a draft PR, or@MelvinBot <your feedback>to refine this analysis.Ollyws commentedon Feb 19, 2026
I can't seem to reproduce this by navigating the the trips page.
mountiny commentedon Feb 19, 2026
It might not be easily reproducible, is it happening for more users?
115 remaining items
melvin-bot commentedon Jun 11, 2026
@QichenZhu Whoops! This issue is 2 days overdue. Let's get this updated quick!
QichenZhu commentedon Jun 12, 2026
Pretty sure it's sorted.
https://expensify.sentry.io/issues/?groupStatsPeriod=auto&query=getActivePolicy%20release.version%3A%3E9.3.87-0&referrer=issue-list&statsPeriod=90d
melvin-bot commentedon Jun 15, 2026
@QichenZhu Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!
QichenZhu commentedon Jun 16, 2026
I think we can close this.
mountiny commentedon Jun 16, 2026
Sounds like we are done