sentry-javascript icon indicating copy to clipboard operation
sentry-javascript copied to clipboard

[Next.js] Custom Error instanceof check fails in beforeSend hook on Server Component

Open developer-choi opened this issue 1 month ago • 5 comments

Is there an existing issue for this?

  • [x] I have checked for existing issues https://github.com/getsentry/sentry-javascript/issues
  • [x] I have reviewed the documentation https://docs.sentry.io/
  • [x] I am using the latest SDK release https://github.com/getsentry/sentry-javascript/releases

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/nextjs

SDK Version

8

Framework Version

Nextjs 14.2.4

Link to Sentry event

https://choeyujin.sentry.io/issues/7050074435/?query=is%3Aunresolved&referrer=issue-stream

Reproduction Example/SDK Setup

https://github.com/developer-choi/reproduce-sentry-instanceof-2025-11-21

Steps to Reproduce

https://github.com/developer-choi/reproduce-sentry-instanceof-2025-11-21?tab=readme-ov-file#reproduction-steps

Expected Result

=== Step 1: Server Component catch block === instanceof CustomApiError: true ✅

=== Step 2: beforeSend === instanceof CustomApiError: true ✅

Actual Result

=== Step 1: Server Component catch block === instanceof CustomApiError: true ✅

=== Step 2: beforeSend === instanceof CustomApiError: false ❌

Additional Context

Unfortunately, due to production constraints, I cannot upgrade to the latest Sentry version yet. This error is occurring in version 8

Priority

React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it.

developer-choi avatar Nov 21 '25 06:11 developer-choi

JS-1188

linear[bot] avatar Nov 21 '25 06:11 linear[bot]

Thanks for the issue - also thanks a lot for the reproduction, that helped quite a lot. This actually also happens on the latest SDK with NextJS 16. However I am not quite sure if it can be solved just like this.

It seems that the instrumentation.ts gets its own bundle and separates itself from the SSR bundle, so there are two different CustomApiError errors which result exactly in this scenario.

@chargome not sure if the bundles can be adapted here.

JPeer264 avatar Nov 21 '25 15:11 JPeer264

@developer-choi you should be able to get the original Exception like this:

beforeSend: function (event, hint) {
  const exception = hint.originalException;
  console.log(exception instanceof CustomApiError); // true
   // ...
},

chargome avatar Dec 02 '25 12:12 chargome

@developer-choi you should be able to get the original Exception like this:

@chargome

It's still not working.

https://github.com/developer-choi/reproduce-sentry-instanceof-2025-11-21/commit/6472d1318b252e623840351263914ffb6348b98c

Image

developer-choi avatar Dec 07 '25 09:12 developer-choi

I tried a few things and I do not think this is an issue with the SDK itself, if you try exporting a class (doesn't need to extend anything) and if you try to check it with instanceof using a global method injected from instrumentation.ts it will still fail that check.

// instrumentation.ts
(global as any).checkBamboozler = (b: any) => {
  console.log('checkBamboozler', b instanceof Bamboozler);
  
  return b instanceof Bamboozler;
};
// Page.tsx
const bamboozler = new Bamboozler('test');
// This works
console.log('passes local call check:', bamboozler instanceof Bamboozler);
// This fails
console.log('cross-boundary check:', (global as any).checkBamboozler(bamboozler));

Probably cross-boundary modules are at play here, I tested the creation timestamp by assigning a static timestamp to it

export class Bamboozler {
  static __createdAt = Date.now();
}

Logging the Bamboozler.__createdAt at both the global function and the server-component yields two different timestamps, which suggests two different class definitions being evaluated.

passes local call check: true
Bamboozler.__createdAt: 1765192933388
checkBamboozler false
Bamboozler.__createdAt: 1765192930631

I think your current workaround is fine, you could add a discriminator boolean property like __isCustomApi and check for that instead of the name or other properties.

logaretm avatar Dec 08 '25 11:12 logaretm

@logaretm Thank you for the insight!

@chargome I’m curious what the next steps are for this issue now.

Since it appears this isn’t a bug with the Sentry SDK itself (based on @logaretm's explanation), should I wait for an official recommendation on the best workaround?

I'm also wondering who would be the right person to provide that guidance.

developer-choi avatar Dec 12 '25 00:12 developer-choi

@developer-choi I suppose this is something you can ask or create an issue for in the Next.js repo, from our side there is not a lot we can do on the SDK level here since this is all user/custom code so we can't really enforce conventions or practices.

Thanks for opening the issue and making us aware of it though, I will close it for now.

logaretm avatar Dec 12 '25 10:12 logaretm