getsentry / sentry-javascript

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

Sentry/Next.js: tags are not added for exceptions logged in `app/error.tsx` #13944

Open christianvuerings opened 2 days ago

christianvuerings commented 2 days ago

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/nextjs

SDK Version

8.32.0

Framework Version

Next.js 14.2.12

Link to Sentry event

https://cambly-inc.sentry.io/issues/5978793591/?project=234235&query=TEST_ERROR_DEFG_1234&referrer=issue-stream&statsPeriod=7d&stream_index=0

Reproduction Example/SDK Setup

import { type Options, type Integration } from "@sentry/types";

const sentryConfig: Options & { integrations: Integration[] } = {
  dsn: "https://9c3f154b2e064abbb12a3901d3c68cd6@o106476.ingest.sentry.io/234235",
  release: `cambly-frontend@development`,
  environment: "development",
  debug: true,
  allowUrls: [
    "webpack-internal://",
    "localhost:8080",
    "localhost:8084",
  ],
  integrations: [],
  beforeSend: (event) => {
    // For debugging
    console.log("///// event beforeSend", {
      tags: event.tags ? JSON.stringify(Object.keys(event.tags)) : null,
    });

    return event;
  },
  tracesSampler(): number {
    return process.env.NODE_ENV !== "production" ? 1 : 0.05;
  },
};

Steps to Reproduce

  1. Create a app/error.tsx file:
    
    "use client";

import { useEffect, type ReactElement } from "react"; import * as Sentry from "@sentry/nextjs";

export default function Error({ error, reset, }: { error: Error & { digest?: string }; reset: () => void; }): ReactElement { console.log("///// captured before", error.__sentry_captured__); useEffect(() => { Sentry.withScope((scope) => { scope.clear(); scope.setTag("cambly.captureLocationTemp", "nextjsPageErrorAppError"); Sentry.captureException(error); }); }, [error]);

return (

Something went wrong{" "}

); }


2. Create a page route `app/page.tsx`:
```js
"use client";

import { type ReactElement } from "react";
import { useSearchParams } from "next/navigation";

export default function Page(): ReactElement {

  const throwErrorIntentionally = useSearchParams().get("throwErrorIntentionally");
  if (throwErrorIntentionally === "true") {
    throw new Error("TEST_ERROR_DEFG_1234");
  }

  return (
   <h1>Test</h1>
  );
}
  1. Go to http://localhost:8080?throwErrorIntentionally=true

Expected Result

Error contains cambly.captureLocationTemp tag

Actual Result

Error does not contain cambly.captureLocationTemp

christianvuerings commented 2 days ago

Notes

Lms24 commented 2 days ago

Hey @christianvuerings thanks for writing in!

I think your suspicion that something else is capturing the error before it's caught by the error page is correct. We can probably find out what that is by looking at event.exception.values[0].mechanism. Would you mind logging this out in your beforeSend hook and reporting back?

Side-note: I see you'Re calling scope.clear() which is fairly destructive. Is there a specific reason for that? This pretty much wipes almost everything that the SDK currently stores on the scope for this request, including stuff like trace information. So if your error on the server is throwing an error in the browser, these won't be linked in the Sentry UI. Not the end of the world of course but just a heads-up :)

christianvuerings commented 1 day ago

I think your suspicion that something else is capturing the error before it's caught by the error page is correct. We can probably find out what that is by looking at event.exception.values[0].mechanism. Would you mind logging this out in your beforeSend hook and reporting back?

@Lms24 event.exception.values[0].mechanism always logs instrument which is the same value as what we see for the exception online: Image

Assuming this is Sentry auto instrumenting exceptions, should autoInstrumentAppDirectory set to false fix this? We tried that and also set autoInstrumentServerFunctions and autoInstrumentMiddleware to false without any luck. It always logs instrument and does not add the tag.

What we want to achieve is for exceptions that hit the error boundary to get a specific tag - e.g. cambly.captureLocation set to nextjsPageError but if Sentry already captures those exceptions, we're not sure how to do that.

Side-note: I see you'Re calling scope.clear() which is fairly destructive. Is there a specific reason for that? This pretty much wipes almost everything that the SDK currently stores on the scope for this request, including stuff like trace information. So if your error on the server is throwing an error in the browser, these won't be linked in the Sentry UI. Not the end of the world of course but just a heads-up :)

Thanks for pointing that out. It was just for debugging purposes to see if that would allow us to set the tag and not something we use in production.