Summary
Setting maskAllText: false (or any of maskAllImages / maskAllVectors: false) on mobileReplayIntegration has no effect when the React Native app uses the New Architecture (Fabric + TurboModules) on Android. Captured replays show all text / images / vectors fully masked regardless of the option value.
Confirmed on-device on @sentry/react-native@7.2.0 (which pulls in sentry-android-replay@8.21.1).
Hypothesis
The v7.5 changelog mentions the experimental Canvas Capture Strategy: "If this strategy is used, all text and images will be masked, regardless of any masking configuration." Our observation is consistent with the SDK selecting Canvas (not PixelCopy) when running on Fabric, which forces the all-mask behavior.
What's missing is either (a) an opt-in to PixelCopy on Fabric or (b) a Canvas implementation that honors maskAllText: false. Either would unblock the use case.
Environment
@sentry/react-native: 7.2.0
sentry-android-replay: 8.21.1 (transitive)
- React Native: 0.81.5
- Fabric: enabled (
react_native_context.fabric: true on captured events)
- TurboModules: enabled
- JS engine: Hermes
- Device: Pixel 7, Android 16
- App built with EAS,
expo-dev-client runtime
Reproduction
Sentry.init({
dsn,
enableNative: true,
replaysOnErrorSampleRate: 1.0,
integrations: [
Sentry.mobileReplayIntegration({
maskAllText: false,
maskAllImages: false,
maskAllVectors: false,
}),
],
});
// Then trigger an error:
Sentry.captureException(new Error("test"));
- Build an APK with Fabric / New Architecture enabled.
- Install on Android device, trigger the error.
- Open the resulting replay in the Sentry dashboard.
- Expected: text content visible in the captured frames.
- Actual: all text masked.
What we verified
- The merged options reach the bundle correctly:
maskAllText: false is present in the JS bundle Metro serves.
RNSentryModuleImpl.java (packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java) reads mobileReplayOptions.maskAllText and calls androidReplayOptions.setMaskAllText(false).
SentryReplayOptions.setMaskAllText(false) (io.sentry:sentry@8.21.1) adds android.widget.TextView to unmaskViewClasses — verified against the published source.
<Text> in RN renders as ReactTextView extends android.widget.TextView, which would match the unmask rule via the Class.superclass walk in ViewHierarchyNode.shouldMask — but only if the view-hierarchy strategy is reading the actual native views (PixelCopy), not screen pixels (Canvas).
So the option flow is correct end-to-end on the SDK; the result mismatch points to the recording strategy.
Asks
- Is the Canvas strategy auto-selected on Fabric in 7.x / 8.x? Confirming intent helps us decide whether to upgrade or wait.
- Is there a config knob to force PixelCopy on Fabric (Sentry RN init option, gradle property, or replay option)?
- Is there a roadmap version where Canvas honors
maskAllText: false or PixelCopy works on Fabric?
Happy to provide more diagnostics. Thanks!
Summary
Setting
maskAllText: false(or any ofmaskAllImages/maskAllVectors: false) onmobileReplayIntegrationhas no effect when the React Native app uses the New Architecture (Fabric + TurboModules) on Android. Captured replays show all text / images / vectors fully masked regardless of the option value.Confirmed on-device on
@sentry/react-native@7.2.0(which pulls insentry-android-replay@8.21.1).Hypothesis
The v7.5 changelog mentions the experimental Canvas Capture Strategy: "If this strategy is used, all text and images will be masked, regardless of any masking configuration." Our observation is consistent with the SDK selecting Canvas (not PixelCopy) when running on Fabric, which forces the all-mask behavior.
What's missing is either (a) an opt-in to PixelCopy on Fabric or (b) a Canvas implementation that honors
maskAllText: false. Either would unblock the use case.Environment
@sentry/react-native: 7.2.0sentry-android-replay: 8.21.1 (transitive)react_native_context.fabric: trueon captured events)expo-dev-clientruntimeReproduction
What we verified
maskAllText: falseis present in the JS bundle Metro serves.RNSentryModuleImpl.java(packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java) readsmobileReplayOptions.maskAllTextand callsandroidReplayOptions.setMaskAllText(false).SentryReplayOptions.setMaskAllText(false)(io.sentry:sentry@8.21.1) addsandroid.widget.TextViewtounmaskViewClasses— verified against the published source.<Text>in RN renders asReactTextView extends android.widget.TextView, which would match the unmask rule via theClass.superclasswalk inViewHierarchyNode.shouldMask— but only if the view-hierarchy strategy is reading the actual native views (PixelCopy), not screen pixels (Canvas).So the option flow is correct end-to-end on the SDK; the result mismatch points to the recording strategy.
Asks
maskAllText: falseor PixelCopy works on Fabric?Happy to provide more diagnostics. Thanks!