react-native-purchases icon indicating copy to clipboard operation
react-native-purchases copied to clipboard

App crashes with Reflect.construct.apply error during Purchases SDK log handler setup (Expo 54, RN 0.81.4, React 19)

Open yahavf6 opened this issue 2 months ago • 4 comments

Checklist:

  • I have updated Purchases SDK to the latest version (9.5.1)
  • I have read the https://github.com/RevenueCat/react-native-purchases/blob/main/CONTRIBUTING.md
  • I have searched the https://community.revenuecat.com
  • I have read https://docs.revenuecat.com/
  • I have searched for https://github.com/RevenueCat/react-native-purchases/issues

Describe the bug

The app crashes immediately on launch with a Reflect.construct error originating from the Purchases SDK's error logging mechanism. The crash occurs when the SDK attempts to set up its log handler, specifically when creating a custom error class for stack trace capture.

  1. Environment a. Platform: iOS (development simulator) b. SDK version: [email protected] c. OS version: macOS Darwin 24.6.0 (iOS Simulator) d. Xcode/Android Studio version: Xcode (version TBD based on macOS 24.6.0) e. React Native version: 0.81.4 f. SDK installation: Package manager (pnpm 10.12.3) g. How widespread is the issue: 100% of launches in development environment h. IOS: 26.0.1
  2. Debug logs that reproduce the issue
  Code: construct.js
    2 | var setPrototypeOf = require("./setPrototypeOf.js");
    3 | function _construct(t, e, r) {
  > 4 |   if (isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
      |                                                                 ^
    5 |   var o = [null];
    6 |   o.push.apply(o, e);
    7 |   var p = new (t.bind.apply(t, o))();

  Call Stack:
    construct (apps/mobile/<native>)
    apply (apps/mobile/<native>)
    _construct
  (node_modules/.pnpm/@[email protected]/node_modules/@babel/runtime/helpers/construct.js:4:65)
    Wrapper
  (node_modules/.pnpm/@[email protected]/node_modules/@babel/runtime/helpers/wrapNativeSuper.js:15:23)
    construct (apps/mobile/<native>)
    _callSuper
  (node_modules/.pnpm/@[email protected]/node_modules/@babel/runtime/helpers/callSuper.js:5:108)
    NamelessError (node_modules/.pnpm/@[email protected][email protected][email protected]_react-native@
  [email protected]/node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:102:20)
    captureCurrentStack (node_modules/.pnpm/@[email protected][email protected][email protected]_react-n
  [email protected][email protected]/node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:106:27)
    HMRClient.log (node_modules/.pnpm/@[email protected][email protected][email protected]_react-native@
  [email protected]/node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:39:79)
    console.level (node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_react@19.
  1.0/node_modules/react-native/Libraries/Core/setUpDeveloperTools.js:41:24)
    setLogHandler$argument_0 (node_modules/.pnpm/[email protected][email protected]_react
  [email protected][email protected]/node_modules/react-native-purchases/dist/purchases.js:114:38)
    eventEmitter.addListener$argument_1 (node_modules/.pnpm/[email protected]_react-native-web@0
  [email protected][email protected]/node_modules/react-native-purchases/dist/purchases.js:72:21)
  1. Steps to reproduce - Install [email protected] in an Expo 54.0.11 project with React Native 0.81.4 - Import and initialize the Purchases SDK - Launch the app in development mode with Expo Metro bundler - Expected behavior: App launches successfully with Purchases SDK initialized - Actual behavior: App crashes immediately with Reflect.construct error during SDK initialization
  2. Other information - The error originates from purchases.js:114:38 when setting up the log handler - This appears to be related to Babel runtime helpers (@babel/[email protected]) and how the SDK creates custom error classes for logging - The crash happens before any SDK methods are called, suggesting it's an initialization/setup issue - Environment: Expo 54.0.11, React 19.1.0, React Native 0.81.4 - Package manager: pnpm 10.12.3 - Node.js: v22.19.0 - The issue may be related to the interaction between:
    • Expo Metro runtime's error capturing mechanism
    • react-native-purchases' custom error logging
    • Babel's native super class wrapping helpers - This appears to be a compatibility issue with the newer Expo/React Native/React versions

Additional context This is a monorepo project using Turborepo. The mobile app is an Expo-managed workflow project. The error prevents the SDK from initializing entirely, making the app unusable in development.

yahavf6 avatar Oct 03 '25 10:10 yahavf6

👀 We've just linked this issue to our internal tracker and notified the team. Thank you for reporting, we're checking this out!

RCGitBot avatar Oct 03 '25 10:10 RCGitBot

@yahavf6 Thanks for reporting 🙏 The team is looking into now and we will hit you up if we have any further questions!

joshdholtz avatar Oct 03 '25 10:10 joshdholtz

I am experiencing the same issue.

Code: construct.js
  2 | var setPrototypeOf = require("./setPrototypeOf.js");
  3 | function _construct(t, e, r) {
> 4 |   if (isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
    |                                                                 ^
  5 |   var o = [null];
  6 |   o.push.apply(o, e);
  7 |   var p = new (t.bind.apply(t, o))();
Call Stack
  construct (<native>)
  apply (<native>)
  _construct (node_modules/@babel/runtime/helpers/construct.js:4:65)
  Wrapper (node_modules/@babel/runtime/helpers/wrapNativeSuper.js:15:23)
  construct (<native>)
  _callSuper (node_modules/@babel/runtime/helpers/callSuper.js:5:108)
  NamelessError (node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:102:20)
  captureCurrentStack (node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:106:27)
  HMRClient.log (node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:39:79)
  console.level (node_modules/react-native/Libraries/Core/setUpDeveloperTools.js:41:24)
  apply (<native>)
  i (node_modules/@logrocket/react-native/dist/build.js:1:100406)
  setLogHandler$argument_0 (node_modules/react-native-purchases/dist/purchases.js:114:38)
  eventEmitter.addListener$argument_1 (node_modules/react-native-purchases/dist/purchases.js:72:21)
  apply (<native>)
  emit (node_modules/react-native/Libraries/vendor/emitter/EventEmitter.js:130:36)
  apply (<native>)
  <anonymous> (node_modules/@babel/runtime/helpers/superPropGet.js:6:19)
  RCTDeviceEventEmitterImpl#emit (node_modules/react-native/Libraries/EventEmitter/RCTDeviceEventEmitter.js:33:5)

Although I believe the specific error code location is not related to this problem.

Code: construct.js
  2 | var setPrototypeOf = require("./setPrototypeOf.js");
  3 | function _construct(t, e, r) {
> 4 |   if (isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
    |                                                                 ^
  5 |   var o = [null];
  6 |   o.push.apply(o, e);
  7 |   var p = new (t.bind.apply(t, o))();

After temporarily disabling the Purchases SDK. For an unrelated different error in my app, I get the same code location strace. I am not fully understanding this yet, but I expect this "code location trace"-issue to be some quirk with the latest version of Expo/React native?

 ERROR  Cannot set prop 'borderRadius' on view 'class expo.modules.image.ExpoImageViewWrapper'
→ Caused by: com.facebook.react.bridge.UnexpectedNativeTypeException: Value for borderRadius cannot be cast from String to double 

Code: construct.js
  2 | var setPrototypeOf = require("./setPrototypeOf.js");
  3 | function _construct(t, e, r) {
> 4 |   if (isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
    |                                                                 ^
  5 |   var o = [null];
  6 |   o.push.apply(o, e);
  7 |   var p = new (t.bind.apply(t, o))();
Call Stack
  construct (<native>)
  apply (<native>)
  _construct (node_modules/@babel/runtime/helpers/construct.js:4:65)
  Wrapper (node_modules/@babel/runtime/helpers/wrapNativeSuper.js:15:23)
  construct (<native>)
  _callSuper (node_modules/@babel/runtime/helpers/callSuper.js:5:108)
  NamelessError (node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:102:20)
  captureCurrentStack (node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:106:27)
  HMRClient.log (node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:39:79)
  console.level (node_modules/react-native/Libraries/Core/setUpDeveloperTools.js:41:24)
  NativeJSLogger.addListener$argument_1 (node_modules/expo-modules-core/src/sweet/setUpJsLogger.fx.ts:46:22)

niek-dewit avatar Oct 12 '25 12:10 niek-dewit

I am experiencing the same issue.

Code: construct.js
  2 | var setPrototypeOf = require("./setPrototypeOf.js");
  3 | function _construct(t, e, r) {
> 4 |   if (isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
    |                                                                 ^
  5 |   var o = [null];
  6 |   o.push.apply(o, e);
  7 |   var p = new (t.bind.apply(t, o))();
Call Stack
  construct (<native>)
  apply (<native>)
  _construct (node_modules/@babel/runtime/helpers/construct.js:4:65)
  Wrapper (node_modules/@babel/runtime/helpers/wrapNativeSuper.js:15:23)
  construct (<native>)
  _callSuper (node_modules/@babel/runtime/helpers/callSuper.js:5:108)
  NamelessError (node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:102:20)
  captureCurrentStack (node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:106:27)
  HMRClient.log (node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:39:79)
  console.level (node_modules/react-native/Libraries/Core/setUpDeveloperTools.js:41:24)
  apply (<native>)
  i (node_modules/@logrocket/react-native/dist/build.js:1:100406)
  setLogHandler$argument_0 (node_modules/react-native-purchases/dist/purchases.js:114:38)
  eventEmitter.addListener$argument_1 (node_modules/react-native-purchases/dist/purchases.js:72:21)
  apply (<native>)
  emit (node_modules/react-native/Libraries/vendor/emitter/EventEmitter.js:130:36)
  apply (<native>)
  <anonymous> (node_modules/@babel/runtime/helpers/superPropGet.js:6:19)
  RCTDeviceEventEmitterImpl#emit (node_modules/react-native/Libraries/EventEmitter/RCTDeviceEventEmitter.js:33:5)

Although I believe the specific error code location is not related to this problem.

Code: construct.js
  2 | var setPrototypeOf = require("./setPrototypeOf.js");
  3 | function _construct(t, e, r) {
> 4 |   if (isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
    |                                                                 ^
  5 |   var o = [null];
  6 |   o.push.apply(o, e);
  7 |   var p = new (t.bind.apply(t, o))();

After temporarily disabling the Purchases SDK. For an unrelated different error in my app, I get the same code location strace. I am not fully understanding this yet, but I expect this "code location trace"-issue to be some quirk with the latest version of Expo/React native?

 ERROR  Cannot set prop 'borderRadius' on view 'class expo.modules.image.ExpoImageViewWrapper'
→ Caused by: com.facebook.react.bridge.UnexpectedNativeTypeException: Value for borderRadius cannot be cast from String to double 

Code: construct.js
  2 | var setPrototypeOf = require("./setPrototypeOf.js");
  3 | function _construct(t, e, r) {
> 4 |   if (isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
    |                                                                 ^
  5 |   var o = [null];
  6 |   o.push.apply(o, e);
  7 |   var p = new (t.bind.apply(t, o))();
Call Stack
  construct (<native>)
  apply (<native>)
  _construct (node_modules/@babel/runtime/helpers/construct.js:4:65)
  Wrapper (node_modules/@babel/runtime/helpers/wrapNativeSuper.js:15:23)
  construct (<native>)
  _callSuper (node_modules/@babel/runtime/helpers/callSuper.js:5:108)
  NamelessError (node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:102:20)
  captureCurrentStack (node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:106:27)
  HMRClient.log (node_modules/@expo/metro-runtime/src/metroServerLogs.native.ts:39:79)
  console.level (node_modules/react-native/Libraries/Core/setUpDeveloperTools.js:41:24)
  NativeJSLogger.addListener$argument_1 (node_modules/expo-modules-core/src/sweet/setUpJsLogger.fx.ts:46:22)

same here

aytaceminoglu avatar Oct 12 '25 14:10 aytaceminoglu