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

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