Skip to content

Mobile Replay (Android, Fabric/New Architecture): masked content briefly unmasked during scroll and on captureException #6393

Description

@fant0mex

What React Native libraries do you use?

  • React Native without Frameworks
  • React Navigation
  • Hermes
  • RN New Architecture

Are you using sentry.io or on-premise?

sentry.io (SaaS)

Are you using any other error monitoring solution alongside Sentry?

No

@sentry/react-native SDK Version

8.16.0

How does your development environment look like?

System:
  OS: macOS 26.5.1
  CPU: (12) arm64 Apple M4 Pro
  Memory: 452.02 MB / 48.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 24.15.0
    path: ~/.local/state/fnm_multishells/2469_1782897781390/bin/node
  Yarn:
    version: 1.22.22
    path: ~/.local/state/fnm_multishells/2469_1782897781390/bin/yarn
  npm:
    version: 11.12.1
    path: ~/.local/state/fnm_multishells/2469_1782897781390/bin/npm
  Watchman:
    version: 2026.04.20.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.16.2
    path: /Users/joseph.hobson/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 25.4
      - iOS 26.4
      - macOS 26.4
      - tvOS 26.4
      - visionOS 26.4
      - watchOS 26.4
  Android SDK:
    API Levels:
      - "35"
    System Images:
      - android-35 | Google APIs ARM 64 v8a
    Android NDK: Not Found
IDEs:
  Android Studio: 2026.1 AI-261.23567.138.2611.15646644
  Xcode:
    version: 26.4.1/17E202
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.13
    path: /usr/bin/javac
  Ruby:
    version: 3.3.11
    path: /Users/joseph.hobson/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli":
    installed: 20.1.3
    wanted: ^20.1.3
  react:
    installed: 19.2.0
    wanted: 19.2.0
  react-native:
    installed: 0.83.6
    wanted: 0.83.6
  react-native-macos: Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: true
  newArchEnabled: true

Platform affected: Android only (not reproduced on iOS).

Sentry.init()

const mobileReplayIntegration = Sentry.mobileReplayIntegration({
  maskAllText: true,
  maskAllImages: false,
  maskAllVectors: false,
  enableViewRendererV2: true,
  beforeErrorSampling: shouldCaptureReplayForError, // gates buffer-mode replay by error type
});

Sentry.init({
  dsn: "https://...@sentry.io/...",
  integrations: [mobileReplayIntegration, navigationIntegration],
  replaysSessionSampleRate: 0.00125, // 0.125%
  replaysOnErrorSampleRate: 1.0, // in the environment used to reproduce
  replaysSessionQuality: "high", // tested with medium also
  autoInitializeNativeSdk: false,
});

Steps to Reproduce

  1. Build and run the Android app (New Architecture / Fabric enabled, Hermes enabled) with Session Replay configured as above (maskAllText: true).
  2. Navigate to a screen containing unmasked text content, inside a ScrollView.
  3. Trigger Sentry.captureException() (we tested via a useEffect timer firing ~4s after mount, to rule out any custom touch-target/overlay interaction as the cause) while the replay is recording (both replaysSessionSampleRate: 1.0 session-mode and default buffer-mode via replaysOnErrorSampleRate were tested — same result in both).
  4. Also independently reproduced by scrolling the ScrollView on the same screen — masked areas become visible mid-scroll.
  5. Inspect the resulting replay recording in the Sentry dashboard.

Expected Result

Masked text/content (per maskAllText: true) should remain masked in the recorded replay at all times, including at the moment an error is captured and during scroll gestures.

Actual Result

In the replay recording, previously-masked text/content becomes fully visible (unmasked) for roughly 1-2 seconds:

  • At the exact moment captureException fires (reproduced independent of any UI trigger mechanism — confirmed via a useEffect-based timer with no user interaction involved).
  • Independently, during scroll gestures on the same screen (masked areas flash visible mid-scroll, even without any error being captured).

Both behaviors were reproduced only on Android; not observed on iOS with the same masking config. We suspect this is related to how the Android masking overlay/screenshot pipeline (PixelCopy vs Canvas strategy, and whether New Architecture forces one over the other) recomputes mask positions relative to when the underlying screenshot is captured — see related discussion in #6122 (Fabric forces Canvas strategy, ignoring masking options) and #3978 (masked content briefly unmasked on native layout/hierarchy changes, e.g. modal open) which describes the same class of failure (mask desync on layout-affecting events) but not this exact repro (scroll + error-capture timing on Fabric/New Architecture).

Screenshots

Screen.Recording.2026-07-02.at.13.58.26.mov

Metadata

Metadata

Assignees

No one assigned

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    Waiting for: Product Owner

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions