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

TypeError: core.convertIntegrationFnToClass is not a function

Open ollie-nye opened this issue 1 year ago • 17 comments

OS:

  • [ ] Windows
  • [x] MacOS
  • [ ] Linux

Platform:

  • [x] iOS
  • [x] Android

SDK:

  • [x] @sentry/react-native (>= 1.0.0)
  • [ ] react-native-sentry (<= 0.43.2)

SDK version: @sentry/[email protected] via @sentry/[email protected] @sentry/[email protected] via other internal dependencies

react-native version: 0.73.5

Are you using Expo?

  • [x] Yes
  • [ ] No

Are you using sentry.io or on-premise?

  • [x] sentry.io (SaaS)
  • [ ] on-premise

If you are using sentry.io, please post a link to your issue so we can take a look:

Local test only, hasn't made it out to the build yet

Configuration:

(@sentry/react-native)

Sentry.init({
  dsn: config.SENTRY_DSN,
  enabled: !__DEV__,
  initialScope: {
    tags: {
      nativeVersion: Application.nativeApplicationVersion,
    },
  },
  ignoreErrors: [
    ...
  ],
  integrations: [
    new Sentry.ReactNativeTracing({
      routingInstrumentation,
      enableNativeFramesTracking: true,
      enableStallTracking: true,
    }),
  ],
});

I have the following issue:

TypeError: core.convertIntegrationFnToClass is not a function when using Jest to test an exception being reported correctly.

Steps to reproduce:

Test looks something like this:

import * as Sentry from '@sentry/react-native';
it('does the thing', () => {
  expect(Sentry.captureException).not.toHaveBeenCalled();
});

Jest has been set up to ignore transforms for @sentry/react-native, though I've also tried with @sentry/.* with the same outcome

Actual result:

Test suite failed to run

    TypeError: core.convertIntegrationFnToClass is not a function

    > 1 | import * as Sentry from '@sentry/react-native';
        | ^
      2 | it('does the thing', () => {
      3 |   expect(Sentry.captureException).not.toHaveBeenCalled();
      4 | });

      at Object.convertIntegrationFnToClass (../node_modules/src/integrations/breadcrumbs.ts:106:28)
      at Object.<anonymous> (../node_modules/@sentry/browser/cjs/sdk.js:8:21)
      at Object.<anonymous> (../node_modules/@sentry/browser/cjs/index.js:11:13)
      at Object.<anonymous> (../node_modules/@sentry/react-native/src/js/tracing/reactnativetracing.ts:3:1)
      at Object.<anonymous> (../node_modules/@sentry/react-native/src/js/tracing/addTracingExtensions.ts:6:1)
      at Object.<anonymous> (../node_modules/@sentry/react-native/src/js/index.ts:51:1)
      at Object.<anonymous> (src/Test.test.ts:1:1)

Expected result:

A passing test


We're currently migrating from sentry-expo and this behaved under that library but this is the last bit that's stumped us until we can move to @sentry/react-native. Thanks for any help or pointers anyone has!

ollie-nye avatar Jul 02 '24 12:07 ollie-nye

Hi @ollie-nye , thank you for the message, the RN SDK is not compatible with the JS v8 yet, we are working on the new major version as we speak https://github.com/getsentry/sentry-react-native/tree/v6.

If I understand it correct the following core results in the same error?

import * as Sentry from '@sentry/core';
it('does the thing', () => {
  expect(Sentry.captureException).not.toHaveBeenCalled();
});

I would recommend keeping the Sentry JS dependencies on @sentry/[email protected] to avoid issues. From the stack trace it seem like ../node_modules/@sentry/browser is v7 which is correct, but then it load @sentry/core@8 instead of it specified v7 dependency. But I don't see why.

krystofwoldrich avatar Jul 03 '24 16:07 krystofwoldrich

Thanks for picking this up so quick! Importing core directly (with a bit of required mocking) seems to behave as it should do, interestingly:

import * as Sentry from '@sentry/core';

jest.mock('@sentry/core', () => {
  const actual = jest.requireActual('@sentry/core');
  return {
    ...actual,
    captureException: jest.fn(),
  };
});

it('does the thing', () => {
  expect(Sentry.captureException).not.toHaveBeenCalled();
});

Result:

 PASS  src/Test.test.tsx
  ✓ does the thing (1 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.625 s, estimated 1 s

We do have both v7 and v8 core in node_modules, because another dependency is pure javascript so has updated to v8 already. We only have v7 as a direct dependency though, with @sentry/react-native at 5.24.1

ollie-nye avatar Jul 04 '24 10:07 ollie-nye

@ollie-nye Thanks, that sounds correct.

As when directly importing the @sentry/core there is no clash. But when importing @sentry/react-native it's ready for v7 JS and it gets v8 which is not compatible.

It seem like that during the tests the wrong version of the @sentry/core package is loaded.

What version is ../node_modules/@sentry/browser?

krystofwoldrich avatar Jul 04 '24 14:07 krystofwoldrich

Having the same issue after react-native: 0.74.1 Any solution for this?

drweizak avatar Jul 08 '24 11:07 drweizak

@ollie-nye Thanks, that sounds correct.

As when directly importing the @sentry/core there is no clash. But when importing @sentry/react-native it's ready for v7 JS and it gets v8 which is not compatible.

It seem like that during the tests the wrong version of the @sentry/core package is loaded.

What version is ../node_modules/@sentry/browser?

@sentry/core:8.15.0

I am using a monorepo with other apps that use sentry for web. Should i try to force @sentry/core:7.x.x in my local package?

drweizak avatar Jul 08 '24 14:07 drweizak

@ollie-nye I solved this issue by declaring @sentry/[email protected] in packages/package-A/package.json and @sentry/[email protected] in packages/package-B/package.json

This forced the @sentry/[email protected] to be installed in the packages/package-B/node_modules folder, while the @sentry/[email protected] was still installed in the root node_modules because is the most recent version and does not affect my packages/package-A/package.json.

We just need to be aware that this is a temp solution and that now i need to pay attention if the version of each @sentry/core matches with my @sentry/nextjs and/or @sentry/react-native

drweizak avatar Jul 09 '24 09:07 drweizak

@drweizak That seems to have sorted it for us as well, nice catch!

ollie-nye avatar Jul 09 '24 11:07 ollie-nye

@drweizak Thank you for the details.

Before this fix, packages/package-B had only dependency on @sentry/react-native?

Was the @sentry/[email protected] installed in packages/package-B/node_modules/@sentry/react-native/node_modules?

krystofwoldrich avatar Jul 09 '24 15:07 krystofwoldrich

@drweizak Thank you for the details.

Before this fix, packages/package-B had only dependency on @sentry/react-native?

Yes!

Was the @sentry/[email protected] installed in packages/package-B/node_modules/@sentry/react-native/node_modules?

Yes! But for some reason it was importing @sentry/[email protected] from 'node_modules/@sentry/core'

I had never a project that had to declare @sentry/core before. So i am assuming it was the other package @sentry/nextjs.

I am quite new in the monorepo ecosystems (yarn-workspaces), but i am available to help :)

drweizak avatar Jul 10 '24 06:07 drweizak

Same for us, we have @sentry/[email protected] as a direct dependency in the project, and @sentry/[email protected] via another dependency, but seem to only be fetching @sentry/core@v8 through both of those

ollie-nye avatar Jul 10 '24 13:07 ollie-nye

Thank you both for the information,

have you tried to change the metro configuration to better suit the monorepo setup?

I personally have not tried this but, https://metrobundler.dev/docs/configuration/#disablehierarchicallookup option might help. As it should stop metro from resolving the v8 from upper directories.

Plus the app node_modules should be explicitly added to the metro config.

Expo has very detailed docs on using React Native in monorepos. https://docs.expo.dev/guides/monorepos/#3-different-versions-of-dependencies-must-be

Are you project setup in a similar way?

krystofwoldrich avatar Jul 10 '24 15:07 krystofwoldrich

node_modules

My setup is similar to the example given by Expo monorepo docs!

I will try the approach of adding disableHierarchicalLookup in my metro config :)

drweizak avatar Jul 11 '24 07:07 drweizak

Thank you both for the information,

have you tried to change the metro configuration to better suit the monorepo setup?

I personally have not tried this but, https://metrobundler.dev/docs/configuration/#disablehierarchicallookup option might help. As it should stop metro from resolving the v8 from upper directories.

Plus the app node_modules should be explicitly added to the metro config.

Expo has very detailed docs on using React Native in monorepos. https://docs.expo.dev/guides/monorepos/#3-different-versions-of-dependencies-must-be

Are you project setup in a similar way?

Actually i do have already enabled it in metro.config

// 3. Force Metro to resolve (sub)dependencies only from the `nodeModulesPaths`
config.resolver.disableHierarchicalLookup = true;

drweizak avatar Jul 15 '24 08:07 drweizak

i'm running into this same issue. as soon as i upgraded to SDK51 i started to run into this when creating new builds. @krystofwoldrich

"@sentry/react-native": "~5.22.0",

since upgrading to the latest i have the same issues when i try to build our app.

AyoParadis avatar Jul 15 '24 15:07 AyoParadis

@AyoCodess have you tried this approach 👇

@ollie-nye I solved this issue by declaring @sentry/[email protected] in packages/package-A/package.json and @sentry/[email protected] in packages/package-B/package.json

This forced the @sentry/[email protected] to be installed in the packages/package-B/node_modules folder, while the @sentry/[email protected] was still installed in the root node_modules because is the most recent version and does not affect my packages/package-A/package.json.

We just need to be aware that this is a temp solution and that now i need to pay attention if the version of each @sentry/core matches with my @sentry/nextjs and/or @sentry/react-native

drweizak avatar Jul 15 '24 15:07 drweizak

@AyoCodess have you tried this approach 👇

@ollie-nye I solved this issue by declaring @sentry/[email protected] in packages/package-A/package.json and @sentry/[email protected] in packages/package-B/package.json

This forced the @sentry/[email protected] to be installed in the packages/package-B/node_modules folder, while the @sentry/[email protected] was still installed in the root node_modules because is the most recent version and does not affect my packages/package-A/package.json.

We just need to be aware that this is a temp solution and that now i need to pay attention if the version of each @sentry/core matches with my @sentry/nextjs and/or @sentry/react-native

Yes, a similar approach worked for me. Thanks.

AyoParadis avatar Jul 15 '24 16:07 AyoParadis

We should add the solution to https://docs.sentry.io/platforms/react-native/troubleshooting/

I solved this issue by declaring @sentry/[email protected] in packages/package-A/package.json and @sentry/[email protected] in packages/package-B/package.json

krystofwoldrich avatar Aug 09 '24 11:08 krystofwoldrich

Also running this. Would be great if we didn't have to do this workaround.

Unfortunately, the workaround does not work for me. When I force @sentry/core to be 7.x I now run into:

Image

TypeError: require(_dependencyMap[0], "@sen(...)ckKeypressInstrumentationHandler is not a function (it is undefined), js engine: hermes

I'm using Expo with CNG.

harrisrobin avatar Oct 25 '24 12:10 harrisrobin

Hi @harrisrobin, thank you for the message,

likely other @sentry/react-native dependencies were not resolved correctly, you need to ensure that all @sentry/react-native -> @sentry/* dependencies get resolved to correct version.

There is the list of dependencies for @sentry/react-native@5.

https://github.com/getsentry/sentry-react-native/blob/v5/package.json#L70-L78

This can be done by the mentioned workaround. Or by changing your monorepo setup or metro.config.js.

To investigate more why this is not working out of the box please share more information about your setup (monorepo setup, metro config).

krystofwoldrich avatar Oct 29 '24 14:10 krystofwoldrich

In my case i was able to remove the workaround because both sentry/next and sentry/react-native are now using the same sentry/core version :)

drweizak avatar Oct 29 '24 15:10 drweizak

We have released https://github.com/getsentry/sentry-react-native/releases/tag/6.0.0

Which depends on JS version 8, so matching of the version should be now much simpler.

Please still keep in mind that the best practice is to use the exact same version of the JS SDK as it the one RN SDK depends on.

krystofwoldrich avatar Nov 06 '24 10:11 krystofwoldrich