Skip to content

[Sentry: APP-HT5] Web onboarding private-domain step loops history.replaceState past Safari's rate limit #97473

Description

@mountiny

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 OwnerCurrent Issue Owner: @gijoe0295

Metadata

Metadata

Labels

BugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributor

Type

No type

Projects

Status
SUBISSUE

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions