getsentry / sentry-javascript

Official Sentry SDKs for JavaScript
https://sentry.io
MIT License
7.94k stars 1.56k forks source link

e.getLastBreadcrumb is not a function. (In 'e.getLastBreadcrumb()', 'e.getLastBreadcrumb' is undefined) #6542

Closed m-nathani closed 1 year ago

m-nathani commented 1 year ago

Environment

SaaS (https://sentry.io/)

Version

7.26.0

Link

https://sentry.io/organizations/umai/issues/3807945297/?project=5264087&referrer=slack

DSN

No response

Steps to Reproduce

it came after enabling replay and upgrading sentry to 7.26.0

Expected Result

should not throw this error.

Actual Result

Throwing exception of breadcrums not found.

getsentry-release commented 1 year ago

Routing to @getsentry/team-web-sdk-frontend for triage. ⏲️

Lms24 commented 1 year ago

Hi @m-nathani please check that you've upgraded all @sentry/* packages, especially @sentry/core which exports this function since 7.26.0.

m-nathani commented 1 year ago

Hi @m-nathani please check that you've upgraded all @sentry/* packages, especially @sentry/core which exports this function since 7.26.0.

Yup they are latest @Lms24

    "@sentry/react": "^7.26.0",
    "@sentry/replay": "^7.26.0",
    "@sentry/tracing": "^7.26.0",
Lms24 commented 1 year ago

When you install @sentry/react, you also add additional packages to your node_modules directory, such as @sentry/core. So just to confirm, is @sentry/core in your node_modules also on version 7.26.0?

Just as a heads-up: I'm transferring this issue to the SDK repo by the way

m-nathani commented 1 year ago

When you install @sentry/react, you also add additional packages to your node_modules directory, such as @sentry/core. So just to confirm, is @sentry/core in your node_modules also on version 7.26.0?

Just as a heads-up: I'm transferring this issue to the SDK repo by the way

Yo, checked its latest:

    "node_modules/@sentry/core": {
      "version": "7.26.0",
      "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.26.0.tgz",
      "integrity": "sha512-ydi236ZoP/xpvLdf7B8seKjCcGc5Z+q9c14tHCFusplPZgLSXcYpiiLIDWmF7OAXO89sSbb1NaFt9YB0LkYdLQ==",
      "dependencies": {
        "@sentry/types": "7.26.0",
        "@sentry/utils": "7.26.0",
        "tslib": "^1.9.3"
      },
      "engines": {
        "node": ">=8"
      }
    },
Lms24 commented 1 year ago

Hmm, usually these problems occur because of version mismatches, when you upgrade e.g. Replay or Browser but for some reason not core or any of the other Sentry dependencies. Is there any chance that you have a browser extension or 3rd party script installed that uses Sentry? Or are you perhaps using multiple Sentry instances yourself (Micro frontend architecture, module federation, etc)?

Also, would you mind sharing your Sentry init config? I'm curious if you're doing anything special when setting up Sentry and Replay

m-nathani commented 1 year ago

Hmm, usually these problems occur because of version mismatches, when you upgrade e.g. Replay or Browser but for some reason not core or any of the other Sentry dependencies. Is there any chance that you have a browser extension or 3rd party script installed that uses Sentry? Or are you perhaps using multiple Sentry instances yourself (Micro frontend architecture, module federation, etc)?

Also, would you mind sharing your Sentry init config? I'm curious if you're doing anything special when setting up Sentry and Replay

Hey..

I am pretty sure the versions are matched after the upgrade..

Moreover, for the extension I am not sure as this is opened on the client browser... However there is not any 3rd party apps that's using sentry.

Lastly, there was an issue for multiple instance which we have solved on our app today and is fixed.

Here the configuration we are doing for sentry:


export const initSentry = () =>
  Sentry.init({
    dsn: process.env.REACT_APP_SENTRY_DSN,
    release: `widget@${version}`,
    environment: `widget@${process.env.REACT_APP_ENVIRONMENT}`,
    ignoreErrors: [
      /ResizeObserver loop limit exceeded.*/,
      /SecurityError: The operation is insecure.*/,
      /SecurityError: Blocked a frame with origin.*/,
      /Non-Error promise rejection captured.*/
    ],
    integrations: [new Integrations.BrowserTracing(), new Replay()],

    // We recommend adjusting this value in production, or using tracesSampler
    // for finer control
    tracesSampleRate: isProductionEnv() ? 0.2 : 1.0,

    // This sets the sample rate to be 10%. You may want this to be 100% while
    // in development and sample at a lower rate in production
    replaysSessionSampleRate: isProductionEnv() ? 0.1 : 1.0,
    // If the entire session is not sampled, use the below sample rate to sample
    // sessions when an error occurs.
    replaysOnErrorSampleRate: 1.0
  });
m-nathani commented 1 year ago

@Lms24 also even after fixing the multiple instance issue we are facing this error.

Here is the link for all the events for this error:

https://sentry.io/organizations/umai/issues/3808072447/events/?project=5264087&referrer=slack

P.S: these events don't show the url or device info etc for this error somehow too

Lms24 commented 1 year ago

Hi @m-nathani you might want to give version 7.27.0 a try, which we just released. In this version you should be able to use the Replay integration directly from @sentry/react. We don't have official docs for this change yet (working on it right now) but the description of #6508 should show you how to use it. For your config, this essentially means removing the import from @sentry/replay and simply calling new Sentry.Replay() in your integrations array. This might help keeping your core package up to date.

fixing the multiple instance issue

Would you mind sharing what this issue was? Are you using Sentry in a micro-frontend setup?

m-nathani commented 1 year ago

Hi @m-nathani you might want to give version 7.27.0 a try, which we just released. In this version you should be able to use the Replay integration directly from @sentry/react. We don't have official docs for this change yet (working on it right now) but the description of #6508 should show you how to use it. For your config, this essentially means removing the import from @sentry/replay and simply calling new Sentry.Replay() in your integrations array. This might help keeping your core package up to date.

fixing the multiple instance issue

Sure will give the 7.27.0 a try today..

Would you mind sharing what this issue was? Are you using Sentry in a micro-frontend setup?

We have a widget modal which get embedded on client applications. So what happened with multiple instances was that:

Whenever our function to open modal was called, sentry was initialized too... so we moved sentry initialization outside of open modal function so that its only initialize when our widget gets mounted.

m-nathani commented 1 year ago

@Lms24 Hii, i have upgraded sentry to 7.27.0 and deployed.

Hopefully the breadcrumb error will be removed...

FYI below the config i have done as you mentioned above:

import * as Sentry from '@sentry/react';
import { Integrations } from '@sentry/tracing';
import {  isProductionEnv } from 'utils/session';

export const initSentry = () =>
  Sentry.init({
    dsn: process.env.REACT_APP_SENTRY_DSN,
    release: `webrms@${process.env.REACT_APP_VERSION}`,
    environment: `webrms@${process.env.REACT_APP_ENVIRONMENT}`,
    ignoreErrors: [
      /ResizeObserver loop limit exceeded.*/,
      /SecurityError: The operation is insecure.*/,
      /SecurityError: Blocked a frame with origin.*/,
      /Can't find variable: PaymentAutofillConfig.*/,
    ],
    integrations: [new Integrations.BrowserTracing(), new Sentry.Replay()],

    // We recommend adjusting this value in production, or using tracesSampler
    // for finer control
    tracesSampleRate: isProductionEnv() ? 0.1 : 0.6,
    // This sets the sample rate to be 10%. You may want this to be 100% while
    // in development and sample at a lower rate in production
    replaysSessionSampleRate: isProductionEnv() ? 0.1 : 1.0,
    // If the entire session is not sampled, use the below sample rate to sample
    // sessions when an error occurs.
    replaysOnErrorSampleRate: 1.0,
  });

P.S: the docs does not seems to be updated though with the new release: https://docs.sentry.io/platforms/javascript/session-replay/

m-nathani commented 1 year ago

Still facing the same error after upgrading to 7.27.0

https://sentry.io/organizations/umai/issues/3808072447/events/?project=5264087&referrer=slack

mikemclin commented 1 year ago

I was getting the same error, but after upgrading from ^7.24.2 to ^7.27.0, the error has gone away for me.

I also realized that I DID have a version mismatch in my lock file. Some of my ^7.24.2 packages were installed as 7.24.2, and some were 7.26.0.

Before

"@sentry/react": "^7.24.2",
"@sentry/replay": "^7.24.2", // installed as 7.26.0
"@sentry/tracing": "^7.24.2"

After

"@sentry/react": "^7.27.0",
"@sentry/replay": "^7.27.0",
"@sentry/tracing": "^7.27.0",
Lms24 commented 1 year ago

Hi @mikemclin thanks for reporting! This is exactly what I'm suspecting to be the problem in such cases. @m-nathani I know that by now I must sound like a broken record (sorry about that) but please take a look at your lock file and if need be also delete and reinstall your node_modules.

Whenever our function to open modal was called, sentry was initialized too... so we moved sentry initialization outside of open modal function so that its only initialize when our widget gets mounted.

Correct me if I'm wrong but to me this sounds like you have two instances of Sentry - one for the "base" site and one for the modal. In this case I'd recommend check if all instances (i.e. all @sentry/* dependencies for them) are aligned and updated to 7.27.0.

As I said, to me the only plausible reason for such an error is that there's some Sentry dependency that's not aligned with the rest.

m-nathani commented 1 year ago

@Lms24,

must sound like a broken record (sorry about that)

I am glad you are responding, and thanks for it 😃 .


Correct me if I'm wrong but to me this sounds like you have two instances of Sentry - one for the "base" site and one for the modal. In this case I'd recommend check if all instances (i.e. all @sentry/* dependencies for them) are aligned and updated to 7.27.0.

That's correct 💯 , however we don't control the base (they are website of our clients). We only have modal that we develop... so mismatch version might be possible from base applications...

in this case what would you recommend ? 🤔

P.S: I am assuming sentry should support older version of its code too ?, because not all web apps who are using sentry would be running on same version. 😕

Lms24 commented 1 year ago

P.S: I am assuming sentry should support older version of its code too ?, because not all web apps who are using sentry would be running on same version

This is a complicated topic unfortunately. We usually try to keep this in mind, however it's not always possible and also not always reasonable to do so. What we for sure don't introduce, is breaking changes for public API (unless we're releasing a major, thereby following semver). However, the change we made that causes this issue, isn't a breaking change in semver terms.

A little more technical background here: The particular change which causes the error you're experiencing is was done in #6495. It's part of an effort of trying to replace parts of the Replay integration that relied on private, SDK-internal API with new (more or less) Replay-specific public API from the core package. We need to do this because keeping around the private API usage is error-prone, brittle and causes side-effects for all users (i.e. also ones who don't use Replay at all), such as an unnecessary bundle size increase.

in this case what would you recommend?

I think your use case is a little complicated to be honest. IIUC, you'd like to use Replay on a website that's not entirely yours. Let me check back with the Replay team if this is an intended use case and if they have ideas how to do this best.

I think your core problem in this case is that Replay is accessing the wrong hub. Internally, Replay calls getCurrentHub which I suspect returns the hub from the base site, which in turn returns the scope that doesn't yet have the getLastBreadcrumb method. What you could try doing is setting your hub as the current hub but I'm not sure if you're able to do this reliably. You can try setting it with Sentry.makeMain. Maybe, you need to create your hub and client manually for this to work.

m-nathani commented 1 year ago

This is a complicated topic unfortunately. We usually try to keep this in mind, however it's not always possible and also not always reasonable to do so. What we for sure don't introduce, is breaking changes for public API (unless we're releasing a major, thereby following semver). However, the change we made that causes this issue, isn't a breaking change in semver terms.

I understand.. however, i am hoping it does not break our client website too.

I think your use case is a little complicated to be honest. IIUC, you'd like to use Replay on a website that's not entirely yours. Let me check back with the Replay team if this is an intended use case and if they have ideas how to do this best.

I would love to hear.. yeah it's complicated for us too... we have to manage so many unwanted errors.. which we tend to keep them in ignoreErrors list... Although with Relay we are so excited to integrate it, because it helps us visually see what our customer is doing and on top of that we have breadcrumbs with stacktrace... It's like adding sugar 🍬 on top of icecream 🍨 . TBH: we are loving it and making our lives more easier to find the right cause of exception.

You can try setting it with Sentry.makeMain. Maybe, you need to create your hub and client manually for this to work.

Sentry.makeMain seems a bit like a shortcut solution.. however not sure how reliable.. but sounds like would replace the client side sentry to mine too 😆.

hub and client manually this sounds really cool for my usecase... however two question here

  1. if i am not wrong then i cannot leverage the use of @sentry/react as i would need to use @sentry/browser to create a client and pass it to hub... ?
  2. i would not need to Sentry.init in this.. and it would be initialized using
const hub = new Hub(client);
Lms24 commented 1 year ago

yeah it's complicated for us too... we have to manage so many unwanted errors

I was suspecting problems like these. Generally, our SDK doesn't work too well in multiple hubs per page scenarios. It's on our roadmap (#5878 > "Exceptions/Scope Data Quality", #5217) to improve and eventually fix this but I can't guarantee that this will happen soon.

if i am not wrong then i cannot leverage the use of @sentry/react as i would need to use @sentry/browser to create a client and pass it to hub... ?

It should work fine with @sentry/react as we're re-exporting everything from @sentry/browser in the React SDK. The Troubleshooting docs are unfortunately just not written in a framework-specific way, hence they talk about the base Browser SDK.

i would not need to Sentry.init in this.. and it would be initialized using...

Yup, first you need to create a BrowserClient and then a Hub: (copied from the troubleshooting docs)

const client = new BrowserClient({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  transport: makeFetchTransport,
  stackParser: defaultStackParser,
  integrations: defaultIntegrations,
});

const hub = new Hub(client);

Note that you need to explicitly pass transport, stackParser and integrations to the client options. This is partly what we abstract away in the Sentry.init function. For adding replay, you'd need to add the integration in adition:

{
  // ...
  integrations: [...defaultIntegrations, new Integrations.BrowserTracing(), new Sentry.Replay()],
}

Let me know how this works out for you

chabou commented 1 year ago

Hi, same issue here. But in our case, we have only one instance of Sentry.

I tried to upgrade to 7.27.0 (from 7.24.0) and to import directly from @sentry/next instead of @sentry/replay. No luck.

It seems to happen only on Safari on iOS (16.1 and 16.2)

edit: and on macOs too

Lms24 commented 1 year ago

Hi @chabou, again, this likely happens because you have multiple Sentry versions in your node_modules and/or yarn/package lock file. Some libraries/3rd party scripts (but also browser extensions) might use Sentry in different versions. So the best advice I can give is to check for that.

chabou commented 1 year ago

I double checked this before my previous message. I am pretty sure that we are using only one version. Here my search result for "@sentry in my monorepo:

49 results - 7 files

yarn.lock:
  5049  
  5050: "@sentry/browser@7.27.0":
  5051    version "7.27.0"

  5054    dependencies:
  5055:     "@sentry/core" "7.27.0"
  5056:     "@sentry/replay" "7.27.0"
  5057:     "@sentry/types" "7.27.0"
  5058:     "@sentry/utils" "7.27.0"
  5059      tslib "^1.9.3"
  5060  
  5061: "@sentry/cli@^1.74.6":
  5062    version "1.74.6"

  5073  
  5074: "@sentry/core@7.27.0":
  5075    version "7.27.0"

  5078    dependencies:
  5079:     "@sentry/types" "7.27.0"
  5080:     "@sentry/utils" "7.27.0"
  5081      tslib "^1.9.3"
  5082  
  5083: "@sentry/integrations@7.27.0":
  5084    version "7.27.0"

  5087    dependencies:
  5088:     "@sentry/types" "7.27.0"
  5089:     "@sentry/utils" "7.27.0"
  5090      localforage "^1.8.1"

  5092  
  5093: "@sentry/nextjs@7.27.0":
  5094    version "7.27.0"

  5099      "@rollup/plugin-virtual" "3.0.0"
  5100:     "@sentry/core" "7.27.0"
  5101:     "@sentry/integrations" "7.27.0"
  5102:     "@sentry/node" "7.27.0"
  5103:     "@sentry/react" "7.27.0"
  5104:     "@sentry/tracing" "7.27.0"
  5105:     "@sentry/types" "7.27.0"
  5106:     "@sentry/utils" "7.27.0"
  5107:     "@sentry/webpack-plugin" "1.20.0"
  5108      chalk "3.0.0"

  5111  
  5112: "@sentry/node@7.27.0":
  5113    version "7.27.0"

  5116    dependencies:
  5117:     "@sentry/core" "7.27.0"
  5118:     "@sentry/types" "7.27.0"
  5119:     "@sentry/utils" "7.27.0"
  5120      cookie "^0.4.1"

  5124  
  5125: "@sentry/react@7.27.0":
  5126    version "7.27.0"

  5129    dependencies:
  5130:     "@sentry/browser" "7.27.0"
  5131:     "@sentry/types" "7.27.0"
  5132:     "@sentry/utils" "7.27.0"
  5133      hoist-non-react-statics "^3.3.2"

  5135  
  5136: "@sentry/replay@7.27.0":
  5137    version "7.27.0"

  5140    dependencies:
  5141:     "@sentry/core" "7.27.0"
  5142:     "@sentry/types" "7.27.0"
  5143:     "@sentry/utils" "7.27.0"
  5144  
  5145: "@sentry/tracing@7.27.0":
  5146    version "7.27.0"

  5149    dependencies:
  5150:     "@sentry/core" "7.27.0"
  5151:     "@sentry/types" "7.27.0"
  5152:     "@sentry/utils" "7.27.0"
  5153      tslib "^1.9.3"
  5154  
  5155: "@sentry/types@7.27.0":
  5156    version "7.27.0"

  5159  
  5160: "@sentry/utils@7.27.0":
  5161    version "7.27.0"

  5164    dependencies:
  5165:     "@sentry/types" "7.27.0"
  5166      tslib "^1.9.3"
  5167  
  5168: "@sentry/webpack-plugin@1.20.0":
  5169    version "1.20.0"

  5172    dependencies:
  5173:     "@sentry/cli" "^1.74.6"
  5174      webpack-sources "^2.0.0 || ^3.0.0"

lib/logger/package.json:
  16    "dependencies": {
  17:     "@sentry/node": "7.27.0",
  18      "moment": "^2.29.1",

packages/api/package.json:
  70      "@react-pdf/renderer": "1.6.8",
  71:     "@sentry/node": "7.27.0",
  72      "@sheet/core": "1.20191114.1",

packages/app/package.json:
  33      "@rebass/markdown": "1.0.0",
  34:     "@sentry/nextjs": "7.27.0",
  35      "@svgr/webpack": "6.4.0",

packages/bo/package.json:
  29      "@auth0/auth0-react": "1.9.0",
  30:     "@sentry/nextjs": "7.27.0",
  31      "@svgr/webpack": "6.4.0",

packages/extension/package.json:
  52          "@auth0/auth0-spa-js": "^1.21.0",
  53:         "@sentry/react": "7.27.0",
  54:         "@sentry/tracing": "7.27.0",
  55          "diacritics": "^1.3.0",

packages/robots/package.json:
  40      "@koa/router": "10.1.0",
  41:     "@sentry/node": "7.27.0",
  42      "@types/koa__router": "8.0.7",

And this is strange that only our few safari users are impacted (this is a B2B saas mainly used with chorme/firefox on Windows)

Should I give a try to the Sentry.makeMain workaround?

Lms24 commented 1 year ago

@chabou makeMain would only make sense in a multi-hub scenario. What kind of app are you building? Also something that's injected into a side like the OP? Or just a conventional web app?

If this is limited to Safari users, my strong suspicion is that there's some Safari browser extension that also uses Sentry. In that case, makeMain might again be worth a try, I guess 😅

chabou commented 1 year ago

We are building a conventional web app.

I will try to ask to our impacted users if they have any safari extension. And I will try the makeMain workaround

m-nathani commented 1 year ago

Note that you need to explicitly pass transport, stackParser and integrations to the client options. This is partly what we abstract away in the Sentry.init function. For adding replay, you'd need to add the integration in adition:

Hi @Lms24 ,

I tried both the ways to check which one works:

  1. first i tried with creating hub and client manually , however the issue with this was i losing some configuration on my project we made on sentry dashboard such as:
    • Tags
    • Inbound filter
    • Error messag filters

Moreover, using this Sentry.showReportDialog function was also not working.. however it worked using Sentry.init thing.

  1. I tried the second option with Sentry.makeMain, it retain all the info of the project with the exception and showReportDialog was working...

However, unfortunately it did not worked to stop getting the breadcrumbs error after doing below:


  Sentry.init({
    dsn: process.env.REACT_APP_SENTRY_DSN,
    ...
  });

  // Once sentry is initialized, call "makeMain" to avoid errors where we have more then one sentry versions, and due to which sentry breaks.
  // "getCurrentHub" overrides global sentry to the most recent version using, be it our or already registered globally,
  // Further info: https://github.com/getsentry/sentry-javascript/issues/6542
  Sentry.makeMain(Sentry.getCurrentHub());
github-actions[bot] commented 1 year ago

This issue has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Backlog or Status: In Progress, I will leave it alone ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀

m-nathani commented 1 year ago

Note that you need to explicitly pass transport, stackParser and integrations to the client options. This is partly what we abstract away in the Sentry.init function. For adding replay, you'd need to add the integration in adition:

Hi @Lms24 ,

I tried both the ways to check which one works:

  1. first i tried with creating hub and client manually , however the issue with this was i losing some configuration on my project we made on sentry dashboard such as:
  • Tags
  • Inbound filter
  • Error messag filters

Moreover, using this Sentry.showReportDialog function was also not working.. however it worked using Sentry.init thing.

  1. I tried the second option with Sentry.makeMain, it retain all the info of the project with the exception and showReportDialog was working...

However, unfortunately it did not worked to stop getting the breadcrumbs error after doing below:

  Sentry.init({
    dsn: process.env.REACT_APP_SENTRY_DSN,
    ...
  });

  // Once sentry is initialized, call "makeMain" to avoid errors where we have more then one sentry versions, and due to which sentry breaks.
  // "getCurrentHub" overrides global sentry to the most recent version using, be it our or already registered globally,
  // Further info: https://github.com/getsentry/sentry-javascript/issues/6542
  Sentry.makeMain(Sentry.getCurrentHub());

Hi @Lms24, can you suggest me what i am doing wrong ? .

Lms24 commented 1 year ago

Hi @m-nathani, apologies for the late reply. I don't think you're doing anything wrong necessarily. Your use case is just something that our SDK doesn't support well and at the moment, we can't do a lot to fix this.

  1. When creating a manual hub you will indeed miss certain global things, such as breadcrumbs, tags or the effects of integrations. The reason for that is that these things internally mostly call getCurrentHub which will only return your custom hub, if you called Sentry.makeMain(yourHub). Otherwise, getCurrentHub will return another hub (e.g. the one your host site has set up). As I said initially, I'm not sure, if makeMain is what you actually want to call though, as this will mess with your host site's Sentry.

  2. Since makeMain doesn't seem to solve the problem anyway, I think we can't really do a lot here. One thing would be to just guard the usage of getLastBreadcrumb but this will lead to incomplete replay breadcrumb data. Not sure if this works but it might be worth a try. I'll open a PR.

One thing I generally want to stress is that Replay does not support being used in parts of a website. So I can't provide you support for replay in your modal as because of how rrweb (the underlying library for replay) works, the whole website will be recorded.

m-nathani commented 1 year ago

@Lms24, Thanks for all the support, and hope the PR works.

I agree to the limitation of the Replay... i hope in future we provide this cool features:

  1. provide easy methods to add multiple sentry instances ( e.g. could be used for diff packages in a mono repo.. or widget in a hosted website)

  2. record certain part of screen, as it might be useful for scenarios where we don't have authorization to record etc...