Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Nextjs App Router Auto instrumentation (How does it work?) #13442

Answered by lforst
lasseklovstad asked this question in Q&A
Discussion options

Intro

I am using Sentry for the first time in my Nextjs application with the new App router v14.2.5. I have followed the nextjs wizard and read the manual setup guide to understand how to use Sentry with nextjs.

As of my understanding sentry will automatically report errors in server components, but for server actions I have to wrap with a special function from sentry. I have tested that errors thrown in actions are reported to sentry. This is all fine and good. Errors in server components on the other hand....

My Issue

I am having a hard time catching errors in server components. First I thought sentry would automatically "just work", but this was not the case. The page I was trying to test errors on had a page.tsx that is a server component and nested server components inside it (maybe this is something sentry doesn't support?).

// app/page.tsx
export default async function Page(){
 const user = await getUserFromDb()
 return <NestedServerComponent />
}
// app/_shared/NestedServerComponent.server.tsx
export default async function NestedServerComponent(){
 // Do some async stuff and maybe throw an error
 return <ClientComponents />
}
  • Errors thrown in Page where reported.
  • Errors thrown in NestedServerComponent was ignored

wrapServerComponentWithSentry function

I also found that sentry exports a function called wrapServerComponentWithSentry that is not documented.

  • When wrapping all components with wrapServerComponentWithSentry errors in Nested server components where catched
  • I would also see different behaviour in dev mode and production npm run dev and npm run build && npm run start.

Is it something wrong with my setup or can someone confirm that Sentry should be able to catch errors in nested server components? Me personally don't like this magic, I would like to read how the magic works? How does sentry know if its a server component and auto wraps it? Does it only wrap server components in page.tsx files?

Another issue (maybe relevant)

When building nextjs and when running in development i get theses wierd warnings from sentry.

Attempted import error: '_optionalChain' is not exported from '@sentry/utils' (imported as '_optionalChain').
Attempted import error: '_nullishCoalesce' is not exported from '@sentry/utils' (imported as '_nullishCoalesce').

If this is why sentry doesn't report the errors it would be nice if it said so aswell. hehe...

You must be logged in to vote

Sorry for the late reply! Yes that issue you linked is very much the culprit of your findings and a limitation by Next.js which they will resolve in Next.js@15 :) The canary also already has the feature shipped necessary to collect server component errors. This is the relevant discussion in the Next.js Repo: vercel/next.js#67149

We also point this out in our docs but it's maybe a bit hard to spot: https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#report-react-component-render-errors

Replies: 1 comment 11 replies

Comment options

After looking at the source code I see this regex in the webpack config fo nextjs sentry plugin:

const isServerComponentResource = (resourcePath: string): boolean => {
 const normalizedAbsoluteResourcePath = normalizeLoaderResourcePath(resourcePath);
 // ".js, .jsx, or .tsx file extensions can be used for Pages"
 // https://beta.nextjs.org/docs/routing/pages-and-layouts#pages:~:text=.js%2C%20.jsx%2C%20or%20.tsx%20file%20extensions%20can%20be%20used%20for%20Pages.
 return (
 appDirPath !== undefined &&
 normalizedAbsoluteResourcePath.startsWith(appDirPath + path.sep) &&
 !!normalizedAbsoluteResourcePath.match(
 // eslint-disable-next-line @sentry-internal/sdk/no-regexp-constructor
 new RegExp(`[\\\\/](page|layout|loading|head|not-found)\\.(${pageExtensionRegex})$`),
 )
 );
 };

Does this mean it only wrapps server components with the names page|layout|loading|head|not-found?

You must be logged in to vote
11 replies
Comment options

I guess I found a issue realted to this: #12525

Comment options

Sorry for the late reply! Yes that issue you linked is very much the culprit of your findings and a limitation by Next.js which they will resolve in Next.js@15 :) The canary also already has the feature shipped necessary to collect server component errors. This is the relevant discussion in the Next.js Repo: vercel/next.js#67149

We also point this out in our docs but it's maybe a bit hard to spot: https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#report-react-component-render-errors

Answer selected by lasseklovstad
Comment options

How are we supposed to setUser in this set up? I have all the necessary error pages but I can't get the user to set server side for the life of me. I have a setUser in the root layout but when an error gets triggered this doesn't seem to get picked up. Any ideas? On nextjs 15.1

Comment options

You need to call setUser both on the client and on the server.

Comment options

I get that but where do we do that? If I do it in a layout it does not seem to propagate, possibly due to how nextjs renders components in parallel? It seems untenable to do setUser in every component. Right now we're wrapping our internal fetch and attempting to setUser when bailing with an error, but this obviously only covers fetch failures. LMK if I'm missing something, it feels like there should be a single global place server side to setUser.

Comment options

Well, that is simply Next.js' design. Server components are run in parallel. What I did in my own app is call setUser() in a server layout that is as close as possible to the root. Then, in the same layout, I render a client component that also calls setUser() for the client.

If you call Sentry.setUser() anywhere on the server during a request, the user is updated for all other server components within the same request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /