-
Notifications
You must be signed in to change notification settings - Fork 108
Description
- I have updated Purchases SDK to the latest version
- I have read the Contribution Guidelines
- I have searched the Community
- I have read docs.revenuecat.com
- I have searched for existing Github issues
Describe the bug
The RevenueCat native Compose paywall UI (react-native-purchases-ui) causes consistent OutOfMemoryError crashes on Android when displaying paywall with social proof carousel. The paywall exhausts the 256MB heap limit during its initial render, even with a simplified template containing no custom images or complex UI elements.
1. Environment
- Platform: Android
- SDK version:
react-native-purchases: 9.6.6react-native-purchases-ui: 9.6.6
- OS version: Android 16
- Android Studio version: N/A (using Expo managed workflow)
- React Native version: 0.79.6
- SDK installation: npm/yarn with Expo managed workflow
- How widespread is the issue: 100% reproducible on test devices when displaying hard paywall via
RevenueCatUI.Paywall
2. Debug logs
The crash occurs during the initial Compose UI measurement/layout phase:
2025-11-18 14:17:38.341 21374-21374 com.example.app com.example.app W Throwing OutOfMemoryError "Failed to allocate a 4224 byte allocation with 2036688 free bytes and 1988KB until OOM, target footprint 268435456, growth limit 268435456; giving up on allocation because <1% of heap free after GC."
2025-11-18 14:17:38.347 21374-21374 AndroidRuntime com.example.app E FATAL EXCEPTION: main
Process: com.example.app, PID: 21374
java.lang.OutOfMemoryError: Failed to allocate a 4224 byte allocation with 2036688 free bytes and 1988KB until OOM, target footprint 268435456, growth limit 268435456; giving up on allocation because <1% of heap free after GC.
at android.os.Parcel.nativeReadString8(Native Method)
at android.os.Parcel.readString8NoHelper(Parcel.java:3436)
at android.os.Parcel$ReadWriteHelper.readString8(Parcel.java:545)
at android.os.Parcel.readString8(Parcel.java:3415)
at android.view.DisplayShape$1.createFromParcel(DisplayShape.java:261)
at android.view.InsetsState.readFromParcel(InsetsState.java:852)
at android.window.WindowMetricsController.getWindowInsetsFromServerForDisplay(WindowMetricsController.java:117)
at androidx.compose.material3.adaptive.AndroidWindowAdaptiveInfo_androidKt.currentWindowSize(AndroidWindowAdaptiveInfo.android.kt:58)
at androidx.compose.material3.adaptive.AndroidWindowAdaptiveInfo_androidKt.currentWindowAdaptiveInfo(AndroidWindowAdaptiveInfo.android.kt:37)
at com.revenuecat.purchases.ui.revenuecatui.components.iconcomponent.IconComponentStateKt.rememberUpdatedIconComponentState(IconComponentState.kt:50)
at com.revenuecat.purchases.ui.revenuecatui.components.iconcomponent.IconComponentViewKt.IconComponentView(IconComponentView.kt:47)
at com.revenuecat.purchases.ui.revenuecatui.components.ComponentViewKt.ComponentView(ComponentView.kt:81)
at com.revenuecat.purchases.ui.revenuecatui.components.stack.StackComponentViewKt$MainStackComponent$stack$1$2$1$1.invoke(StackComponentView.kt:513)
[... extensive Compose layout stack trace ...]
at com.revenuecat.purchases.react.ui.views.ComposeViewWrapper.onMeasure(ComposeViewWrapper.kt:52)
Key observations from logs:
- Memory pressure builds up during onboarding:
Clamp target GC heap from 351MB to 256MB - Multiple blocking GC events before crash:
WaitForGcToComplete blocked Alloc(400-600ms delays) - Heap is at 254-255MB before paywall renders
- Crash occurs during Compose UI measurement, specifically when calculating adaptive window metrics
3. Steps to reproduce
Setup:
- Create a React Native app with Expo managed workflow
- Add RevenueCat paywall using
react-native-purchases-uiat the end of onboarding - Use the default offering
Expected behavior:
Paywall should render successfully without memory issues.
Actual behavior:
App crashes with OutOfMemoryError during paywall's initial Compose measurement phase. The crash is 100% reproducible.
Additional observations:
- Removing all WebP images from onboarding slides does NOT fix the issue
- Removing all custom images from the paywall template does NOT fix the issue
- Memory is already at 254-255MB before the paywall attempts to render
- Adding
android:largeHeap="true"does NOT fix the issue (still crashes at 256MB limit)
4. Other information
Root cause analysis:
The RevenueCat Compose paywall UI appears to have excessive memory overhead when rendering paywalls with social proof carousel. The stack trace shows it's crashing during:
- Adaptive window metrics calculation (
currentWindowAdaptiveInfo) - Icon component state management
- Complex nested Stack/Carousel component composition
The issue appears to be related to:
- Jetpack Compose memory overhead - The native Compose UI requires significantly more memory than React Native views
- Complex component hierarchy - Multiple nested stacks, carousels, and adaptive layouts
- No memory cleanup between screens - Previous onboarding state remains in memory
Workarounds attempted:
- ✅ Removed all images from onboarding slides
- ✅ Simplified paywall template (removed all custom images)
- ✅ Added
android:largeHeap="true" - ❌ None of these resolved the issue
Removing the carousel:
- ✅ This seems to have fixed the crash
Device specifications:
- Heap limit: 256MB (standard Android allocation)
- Memory available at crash: ~2MB (254MB/256MB used)
- React Native memory footprint before paywall: ~200MB