Skip to content

Session Replay resumes capture on didBecomeActive with no delay, causing fatal iOS App Hangs (watchdog kill) #6701

Description

@chanikya-me

What React Native libraries do you use?

React Native without Frameworks

Are you using sentry.io or on-premise?

sentry.io (SaS)

Are you using any other error monitoring solution alongside Sentry?

No

Other Error Monitoring Solution Name

No response

@sentry/react-native SDK Version

8.8.0

How does your development environment look like?

⬇  Place the `npx react-native@latest info` output here. ⬇
System:
  OS: macOS 26.5.1
  CPU: (10) arm64 Apple M5
  Memory: 253.89 MB / 24.00 GB
Binaries:
  Node: 26.0.0
  Yarn: 1.22.22
  npm: 11.18.0
  Watchman: Not Found
IDEs:
  Xcode: 26.6/17F113
Languages:
  Java: 21.0.11
  Ruby: 3.3.6
npmPackages:
  "@react-native-community/cli": 20.1.2
  react: 19.1.0
  react-native: 0.81.1
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: true
  newArchEnabled: true



Sentry.init()

Sentry.init({
  dsn: sentryDsn,
  enabled: true,
  environment: __DEV__ ? 'development' : 'production',
  sendDefaultPii: false,
  tracesSampleRate: 0.2,
  profilesSampleRate: 0.1,
  enableLogs: true,
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
  integrations: [
    navigationIntegration,
    Sentry.mobileReplayIntegration({
      maskAllText: false,
      maskAllImages: false,
      maskAllVectors: false,
      // Skip video / AVKit view trees during Session Replay screenshotting.
      // Traversing RCTVideo (and AVPlayer fullscreen presentation layers) can
      // fatal with -[NSConcreteValue doubleValue] while CA animations run.
      // See: getsentry/sentry-react-native#5548, getsentry/sentry-cocoa#7810
      excludedViewClasses: [
        'RCTVideo',
        'AVPlayer',
        'AVPlayback',
        'AVNowPlaying',
        'AVFullScreen',
        'AVKit',
      ],
    }),
  ],

Steps to Reproduce

Session Replay resumes capture on didBecomeActive with no delay, causing fatal iOS App Hangs (watchdog kill)

Description

On iOS, Session Replay's screenshot pass is resumed synchronously on
UIApplication.didBecomeActiveNotification. Because the capture walks the view
hierarchy and re-renders the window on the main thread, and because iOS applies
its strictest watchdog to foreground transitions, a heavy view tree at resume
can block the main thread past 2s and the app is terminated.

We are seeing this in production as Fatal App Hang Fully Blocked, with
SentrySessionReplay.takeScreenshot as the symbolicated culprit.

The relevant code is SentrySessionReplayIntegration.swift, which wires resume
straight to the notification:

notificationCenter.addObserver(self, selector: #selector(pause),
                               name: UIApplication.didEnterBackgroundNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(resume),
                               name: UIApplication.didBecomeActiveNotification, object: nil)

There is no configurable delay or jitter before the first capture after resume,
and no way to defer it from JS: SentryReplayApi exposes pause/resume/
start/stop natively, but the React Native bridge only forwards
captureReplay and getCurrentReplayId (NativeRNSentry.d.ts), so a React
Native app cannot pause replay across the foreground transition even as a
workaround.

Evidence

Two events from the same issue, on very different hardware, both with the
identical breadcrumb shape:

iPhone XR, iOS 18.1.1

10:17:20.609  app.lifecycle  background
10:17:21.412  device.event   Low memory  LOW_MEMORY
              ... 2h 56m ...
13:13:52.441  app.lifecycle  foreground
13:13:52.593  app.lifecycle  active
13:13:53-54   app's own rehydration requests
13:13:55.628  Fatal App Hang Fully Blocked      <- 3.2s after active

iPhone 16 Pro, iOS 26.6.1

04:40:37.783  app.lifecycle  background
              ... ~4 min ...
04:44:34.536  app.lifecycle  foreground
04:44:34.766  app.lifecycle  active
04:44:34-35   app's own rehydration requests
04:44:36.970  Fatal App Hang Fully Blocked      <- 2.4s after active

Points worth noting:

  • Time spent in background is irrelevant (2h56m vs 4min); the trigger is the
    resume itself.
  • It reproduces on current hardware, not just older devices — an iPhone 16 Pro
    on iOS 26 hit the same group as an iPhone XR on iOS 18.
  • The JS thread is idle in both. This is entirely native.
  • enableViewRendererV2 is on (SDK default), so this is with the fast renderer
    already in use.

Steps to reproduce

  1. Init with Session Replay in buffer mode (replaysOnErrorSampleRate: 1.0).
  2. Open a screen with a large view tree (in our case a chat list backed by a
    long message list).
  3. Background the app.
  4. Return to the foreground while the app also does meaningful work on the main
    thread at resume (state rehydration, list re-render).
  5. On a device under memory pressure this blocks past the watchdog threshold
    and iOS terminates the app.

Reproduction is probabilistic rather than deterministic — it depends on how
much work lands in the same window. We have 4 events across 4 users.

Expected result

Resuming replay after a foreground transition should not be able to terminate
the app. Some possibilities, in rough order of preference:

  1. Defer the first capture after didBecomeActive by a short interval, or
    schedule it off the watchdog-critical window.
  2. Expose an option for that delay in SentryReplayOptions /
    MobileReplayOptions.
  3. Bridge SentryReplayApi's pause/resume to React Native, so apps can at
    least implement the workaround themselves.

Actual result

The first capture runs immediately on didBecomeActive, on the main thread,
and the watchdog kills the app.

Expected Result

No App hang

Actual Result

App hangs after it comes to foreground state

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions