Skip to content

React Native Android layout glitches with session recording #3140

Closed

Description

@Nezz

Bug description

Posthog's session recording on Android with React Native causes layout glitches by resetting the safe area to zero. This was reported earlier, but I managed to make a minimal repro.
#2155

How to reproduce

  1. Check out this minimal repro:
    https://github.com/Nezz/expo-repro/tree/repro/Posthog
  2. Set your API key in PostHogProvider
  3. Run on an Android 15+ device that has some kind of notch or display cutout (I used a Galaxy Fold)
    If you are using bun (but any package manager should work):
bun install
bun android

Expected outcome:

SafeAreaInsets.top should not reset to zero

Actual outcome:

It periodically resets to zero, causing the whole UI to jump. See change log text box:

Image

The issue does not happen on iOS or with enableSessionReplay: false.

Related sub-libraries

  • All of them
  • posthog-js (web)
  • posthog-js-lite (web lite)
  • posthog-node
  • posthog-react-native
  • @posthog/react
  • @posthog/ai
  • @posthog/convex
  • @posthog/nextjs-config
  • @posthog/nuxt
  • @posthog/rollup-plugin
  • @posthog/webpack-plugin

Additional context

Thank you for your bug report – we love squashing them!

Activity

  1. added
    bugSomething isn't working
    on Feb 24, 2026
  2. ablaszkiewicz commented on Feb 24, 2026

    @ablaszkiewicz
    Contributor
  3. marandaneto commented on Feb 24, 2026

    @marandaneto
    Member

    thanks @Nezz will try to reproduce it

  4. marandaneto commented on Feb 26, 2026

    @marandaneto
    Member

    The PostHog Android SDK's session replay takes screenshots via PixelCopy on every throttled draw. The old code created and destroyed a new HandlerThread for every single screenshot (~1/sec). The PixelCopy callback then
    traverses the entire view tree from that background thread to find maskable widgets.

    On Android 15+, which enforces edge-to-edge, this thread churn combined with background view-tree access creates a race condition where rootWindowInsets briefly returns zero values. Since react-native-safe-area-context
    reads these insets via OnPreDrawListener, the safe area periodically flashes to zero, causing the UI to jump.

    This explains why:

    • Increasing androidDebouncerDelayMs helps (fewer screenshots = less thread churn)
    • Debouncing useSafeAreaInsets() helps (masks the transient zeros)
    • Disabling session replay fixes it entirely
    • It only happens on Android 15+ (edge-to-edge enforcement changed insets dispatch)

    The fix (in posthog-android):

    1. Reuse a single HandlerThread for PixelCopy callbacks instead of creating/destroying one per screenshot
    2. Early bail-out checks (isOnDrawnCalled) at the top of generateSnapshot() and findMaskableWidgets() to minimize time spent reading stale view state off the main thread
    3. Reduce allocations during the view tree walk (reusable Rect/Point, Set instead of List for password types, contains(ignoreCase=true) instead of lowercase())

    Im not sure if this alone is enough, but might improve things

  5. Nezz commented on Mar 10, 2026

    @Nezz
    ContributorAuthor

    I tried "posthog-react-native-session-replay": "1.5.1" but sadly I don't see a noticeable improvement so for now we can't enable it on Android.

  6. joaqo commented on Mar 27, 2026

    @joaqo

    Given that the issue seems to be diagnosed, should we be expecting a fix? I'm the creator of the original issue reporting this, so I've been more than a year with no Android session replays.

  7. marandaneto commented on Apr 29, 2026

    @marandaneto
    Member

    there were some improvements on android and ios, please try the latest version and report back if there is still an issue

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions