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
Switch to Classic on mWeb opens the HybridApp instead of staying in the browser #99588
On mWeb, tapping Switch to Classic hands off to the installed HybridApp instead of staying in the browser. In-page mWeb taps should never leave the browser — see Improve app deep link behaviour and test suite.
Version Number: v9.4.51-1 Reproducible in production?: Yes Email or phone of affected tester (no customers):[email protected] Issue reported by: Applause Internal Team Device used: Pixel 7 Pro/Android 17
Action Performed:
Test different sources. Precondition: Account has Switch to Classic in troubleshoot: enter in console if account doesn't show it Onyx.merge('nvp_tryNewDot', {
classicRedirect: {
isLockedToNewDot: false,
},
});
Steps:
Root Cause: This is an OS‑level deep‑link handoff, not an in‑page routing bug. "Switch to Classic" on mWeb navigates the browser to https://www.expensify.com/inbox?... (via openOldDotLink → asyncOpenURL, which does a top‑level _self navigation). Because /inbox is registered as a Universal Link / App Link for the installed Classic/Hybrid app on www.expensify.com, the OS intercepts that cross‑domain navigation and hands off to the native app instead of staying in the browser.
I confirmed the live association file served from www.expensify.com/.well-known/apple-app-site-associationexplicitly lists /inbox and /inbox/ as matched components for the native app, and www.expensify.com/.well-known/assetlinks.json delegates handle_all_urls to the Android Classic/Hybrid package. That is exactly what pulls the tap into the app.
This is not fixable in Expensify/App. App only claims new.expensify.com in its own native config — it neither registers www.expensify.com nor can browser JS suppress a verified OS‑level app‑link handoff. The lever is the deep‑link association config for www.expensify.com and the Classic/Hybrid app's native deep‑link configuration, both of which live outside this repo. This needs an internal engineer to exclude the in‑page mWeb transition path(s) (e.g. /inbox) from Universal Link / App Link matching, in line with the expected behavior in #98061 ("Tapping a link on mWeb expensify.com / new.expensify.com will not deep link into app").
asyncOpenURL/index.web.ts runs Linking.openURL(url, '_self') — a top‑level cross‑domain nav (new.expensify.com → www.expensify.com).
The OS matches www.expensify.com/inbox against the installed native app's verified associated domain and opens the app.
Why App can't fix it
Android intent filters (AndroidManifest.xml) and iOS associated domains only claim new.expensify.com / staging.new.expensify.com — never www.expensify.com. The intercepting app is the installed Classic/Hybrid app.
There is no App‑side referrer/param trick that suppresses a verified app‑link handoff; browser JS cannot override it.
apple-app-site-association → components include {"/": "/inbox"} and {"/": "/inbox/"} (and paths lists /inbox, /inbox/).
assetlinks.json → delegate_permission/common.handle_all_urls for the Android Classic/Hybrid package.
Note on verification: this behavior can only be reproduced on a physical/emulated mobile device with the Classic/Hybrid app installed — a desktop web browser has no such association and won't hand off, so it can't confirm the repro.
Next steps: This requires a change outside the Expensify/App repo (deep‑link association config for www.expensify.com + the Classic/Hybrid app's native config). Please escalate to an internal engineer with access, ideally tracked alongside #98061.
I think the correct solution would be to adjust such links in a way mobile app can handle them properly (or update the app), so when someone clicks on Switch to Expensify classic, they're correctly redirected to the mobile OD.
Coming back to this issue, is this something you would have time to work on soon @war-in?
P.S. Is everyone reading this sure this is really a near-term priority? Be brave: if you disagree, go ahead and close it out. If someone disagrees, they'll reopen it, and if they don't: one less thing to do!
Activity
MelvinBot commentedon Aug 26, 2026
Issue Analysis
Root Cause: This is an OS‑level deep‑link handoff, not an in‑page routing bug. "Switch to Classic" on mWeb navigates the browser to
https://www.expensify.com/inbox?...(viaopenOldDotLink→asyncOpenURL, which does a top‑level_selfnavigation). Because/inboxis registered as a Universal Link / App Link for the installed Classic/Hybrid app onwww.expensify.com, the OS intercepts that cross‑domain navigation and hands off to the native app instead of staying in the browser.I confirmed the live association file served from
www.expensify.com/.well-known/apple-app-site-associationexplicitly lists/inboxand/inbox/as matched components for the native app, andwww.expensify.com/.well-known/assetlinks.jsondelegateshandle_all_urlsto the Android Classic/Hybrid package. That is exactly what pulls the tap into the app.This is not fixable in
Expensify/App. App only claimsnew.expensify.comin its own native config — it neither registerswww.expensify.comnor can browser JS suppress a verified OS‑level app‑link handoff. The lever is the deep‑link association config forwww.expensify.comand the Classic/Hybrid app's native deep‑link configuration, both of which live outside this repo. This needs an internal engineer to exclude the in‑page mWeb transition path(s) (e.g./inbox) from Universal Link / App Link matching, in line with the expected behavior in #98061 ("Tapping a link on mWebexpensify.com/new.expensify.comwill not deep link into app").Investigation details
Flow that triggers it
TroubleshootPage.tsx/DynamicExitSurveyConfirmPage.tsx:68callopenOldDotLink(CONST.OLDDOT_URLS.INBOX, true).Link.ts:86buildshttps://www.expensify.com/inbox?email=....asyncOpenURL/index.web.tsrunsLinking.openURL(url, '_self')— a top‑level cross‑domain nav (new.expensify.com→www.expensify.com).www.expensify.com/inboxagainst the installed native app's verified associated domain and opens the app.Why App can't fix it
AndroidManifest.xml) and iOS associated domains only claimnew.expensify.com/staging.new.expensify.com— neverwww.expensify.com. The intercepting app is the installed Classic/Hybrid app.Live config evidence (publicly served from www.expensify.com)
apple-app-site-association→componentsinclude{"/": "/inbox"}and{"/": "/inbox/"}(andpathslists/inbox,/inbox/).assetlinks.json→delegate_permission/common.handle_all_urlsfor the Android Classic/Hybrid package.Note on verification: this behavior can only be reproduced on a physical/emulated mobile device with the Classic/Hybrid app installed — a desktop web browser has no such association and won't hand off, so it can't confirm the repro.
Next steps: This requires a change outside the
Expensify/Apprepo (deep‑link association config forwww.expensify.com+ the Classic/Hybrid app's native config). Please escalate to an internal engineer with access, ideally tracked alongside #98061.view run
melvin-bot commentedon Aug 26, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @QichenZhu (
External)Julesssss commentedon Aug 26, 2026
Not open for external contributions
aimane-chnaif commentedon Aug 26, 2026
Please assign me here too
13 remaining items
Julesssss commentedon Sep 10, 2026
Not overdue, in progress
melvin-bot commentedon Sep 15, 2026
@aimane-chnaif Huh... This is 4 days overdue. Who can take care of this?
Julesssss commentedon Sep 18, 2026
Coming back to this issue, is this something you would have time to work on soon @war-in?
war-in commentedon Sep 22, 2026
I think wildcard deeplinks should resolve the issue - #99347
but there are a couple of issues we encountered. Could you check those @Julesssss? 🙏
war-in commentedon Sep 25, 2026
Actually they won't 😅
But here is the PR that should - #102312
The only caveat is that it works only on Android 15+, but I think it's fine (it doesn't work at all now and 15+ are majority of devices)
Also, we'll have to deploy
expensify.com(OD) AASA file with this change{ "/": "*", "?": {"openInBrowser": "true"}, "exclude": true, "comment": "Links opened from NewDot in the browser stay in the browser" },@Julesssss could you help with that? 🙏
Julesssss commentedon Sep 25, 2026
Nice, thanks. Yeah not a problem.
Will get to this when I have a moment
melvin-bot commentedon Oct 12, 2026
This issue has not been updated in over 15 days. @Julesssss, @war-in, @aimane-chnaif eroding to Monthly issue.
P.S. Is everyone reading this sure this is really a near-term priority? Be brave: if you disagree, go ahead and close it out. If someone disagrees, they'll reopen it, and if they don't: one less thing to do!