Sentry
https://expensify.sentry.io/issues/APP-HT5
Impact (snapshot at filing)
- Users (total since first seen): 22
- Events: 38
- Users (last 7d, in 9.4.44–9.4.46): 2
- First seen: 2026-07-16
- Last seen: ongoing (events today)
- Platform: web — Mobile Safari (iOS 18.7) observed; Safari rate limit is what surfaces it
- App version(s): 9.4.45-14 and others in range
- Affected route(s):
/onboarding/private-domain
- View name:
Onboarding_Private_Domain
- Mechanism:
auto.browser.global_handlers.onunhandledrejection
DOMException.code: 18 (SecurityError)
Error
SecurityError: Attempt to use history.replaceState() more than 100 times per 10 seconds
Stack trace (top frames, first-party only)
../node_modules/@react-navigation/native/lib/module/useLinking.js:373:24 (onStateChange)
history.replace({
../node_modules/@react-navigation/native/lib/module/createMemoryHistory.js:128:34 (<object>.replace)
window.history.replaceState({
[native code] (replaceState)
Suspected cause
A navigation-state loop on the onboarding private-domain step. Something re-dispatches navigation on
every state change — a redirect effect whose dependency changes each render, or a
navigate/setParams call in an effect that itself re-triggers the effect — so react-navigation's
useLinking onStateChange fires history.replace repeatedly. Safari caps replaceState at 100
calls per 10 seconds and throws once the loop exceeds it.
The rate limit is the symptom, not the bug: the underlying problem is an unbounded navigation loop
that will also burn CPU and block the onboarding flow on browsers without a cap.
Worth auditing the redirect logic on the private-domain onboarding screen for an effect that
navigates without a guard on the current route/state.
Reproduction
Unknown — see Sentry events linked above. Reaching /onboarding/private-domain (sign up with a
private email domain and proceed through onboarding) on Mobile Safari is the observed context.
Related
- Same
useLinking/createMemoryHistory layer as the pushState SecurityError filed alongside this
one in the same scan (APP-HTY / APP-HNR / APP-CFF), but a different call site and a different root
cause — that one is a malformed path, this one is a loop.
- Found by a 7-day production crash scan of the latest 3 released versions (9.4.44, 9.4.45, 9.4.46)
Upwork Automation - Do Not Edit
Issue Owner
Current Issue Owner: @gijoe0295
Sentry
https://expensify.sentry.io/issues/APP-HT5
Impact (snapshot at filing)
/onboarding/private-domainOnboarding_Private_Domainauto.browser.global_handlers.onunhandledrejectionDOMException.code: 18 (SecurityError)Error
Stack trace (top frames, first-party only)
Suspected cause
A navigation-state loop on the onboarding private-domain step. Something re-dispatches navigation on
every state change — a redirect effect whose dependency changes each render, or a
navigate/setParamscall in an effect that itself re-triggers the effect — so react-navigation'suseLinkingonStateChangefireshistory.replacerepeatedly. Safari capsreplaceStateat 100calls per 10 seconds and throws once the loop exceeds it.
The rate limit is the symptom, not the bug: the underlying problem is an unbounded navigation loop
that will also burn CPU and block the onboarding flow on browsers without a cap.
Worth auditing the redirect logic on the private-domain onboarding screen for an effect that
navigates without a guard on the current route/state.
Reproduction
Unknown — see Sentry events linked above. Reaching
/onboarding/private-domain(sign up with aprivate email domain and proceed through onboarding) on Mobile Safari is the observed context.
Related
useLinking/createMemoryHistorylayer as thepushStateSecurityError filed alongside thisone in the same scan (APP-HTY / APP-HNR / APP-CFF), but a different call site and a different root
cause — that one is a malformed path, this one is a loop.
Upwork Automation - Do Not Edit
Issue Owner
Current Issue Owner: @gijoe0295