Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughThis PR integrates Sentry error monitoring and performance tracing into the docs application. Changes include wrapping Next.js configuration with Sentry integration, adding runtime-specific configuration files for server and edge environments, client-side instrumentation setup, and a global error boundary component for capturing unhandled exceptions. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
🍈 Lychee Link Check Report3660 links: ✅ All links are working!Full Statistics Table
|
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/docs/next.config.mjs (1)
1-55:⚠️ Potential issue | 🟡 MinorFix the trailing backslash typo on line 27; authToken gating is optional.
Your Sentry configuration is well-structured per
@sentry/nextjs@10.38.0. A couple of clarifications:
- Line 27 typo: Remove the trailing
\from the comment (CI\→CI).webpackoptions placement: Your nestedwebpack: { automaticVercelMonitors, treeshake: ... }is the correct modern location for these options (not mixing buckets). BothautomaticVercelMonitorsandtreeshake.removeDebugLoggingare valid here and won't cause issues.authTokenundefined behavior: Whenprocess.env.SENTRY_AUTH_TOKENis missing in non-CI environments,authTokenis simplyundefined, and the build proceeds without attempting uploads—no failure. Explicit CI gating (as suggested below) is defensive and good practice, but not strictly required.Optional defensive CI gating
- authToken: process.env.SENTRY_AUTH_TOKEN, + authToken: process.env.CI ? process.env.SENTRY_AUTH_TOKEN : undefined,Fix the typo. The authToken suggestion is optional; the rest is correct as-is.
apps/docs/src/instrumentation-client.ts (1)
2-29:⚠️ Potential issue | 🟠 MajorLock down Sentry config: env-based DSN, lower sampling rates, and disable PII by default.
The current config poses three real risks on a public docs site:
Hardcoded DSN prevents separate environment configs. Preview/staging deployments will send errors to the same production project, polluting signal and making it harder to troubleshoot issues in isolation. Use
process.env.NEXT_PUBLIC_SENTRY_DSNinstead, so environments can be configured independently.
sendDefaultPii: truecaptures IP addresses, headers, and user-like context by default. This is a privacy concern for a public site—users haven't consented to PII collection by Sentry. The Sentry default isfalsefor good reason. Set it tofalseunless you have explicit consent and documented need.
tracesSampleRate: 1means 100% of transactions (all page navigation, API calls, etc.) are sent to Sentry. On a docs site with meaningful traffic, this will quickly exceed your quota (5M spans/month on standard plans) and trigger pay-as-you-go overage charges. Production should use a much lower rate (~0.1 = 10% is a common starting point), configurable via env var.As for
enableLogs: true—it's a valid option that pipes console logs into Sentry. There's no inherent problem, but gating it to dev-only (process.env.NODE_ENV !== "production") reduces noise in production events.Apply this pattern:
Suggested fix
Sentry.init({ - dsn: "https://e83ce4699e59051fdeaa330bf4a0dfb9@o4510879743737856.ingest.us.sentry.io/4510879744000000", + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, - tracesSampleRate: 1, + tracesSampleRate: + process.env.NODE_ENV === "production" + ? Number(process.env.NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE ?? 0.1) + : 1, - enableLogs: true, + enableLogs: process.env.NODE_ENV !== "production", - sendDefaultPii: true, + sendDefaultPii: false, });If
NEXT_PUBLIC_SENTRY_DSNcan be absent in dev/preview, guard the init:if (process.env.NEXT_PUBLIC_SENTRY_DSN) { Sentry.init({ ... }); }
🤖 Fix all issues with AI agents
In `@apps/docs/sentry.edge.config.ts`:
- Around line 1-20: Replace the hardcoded Sentry configuration in Sentry.init:
read dsn from an environment variable (e.g., process.env.SENTRY_DSN) instead of
the literal string, drive tracesSampleRate from an env var with a safe
production default (e.g., parseFloat(process.env.SENTRY_TRACES_SAMPLE_RATE) ||
0.1), set enableLogs based on NODE_ENV (true only in development), and set
sendDefaultPii from an env var defaulting to false (e.g.,
!!JSON.parse(process.env.SENTRY_SEND_DEFAULT_PII || "false")); apply the same
env-driven changes to sentry.server.config.ts so both edge and server configs
use the same safe defaults.
In `@apps/docs/src/app/global-error.tsx`:
- Around line 1-27: Replace the Pages Router-only NextError usage in GlobalError
with a minimal custom error UI and recovery button: inside the GlobalError
component (function GlobalError) remove NextError and render a simple message
and a "Try again" button that calls the reset() function (destructure reset from
the component props) to trigger client-side recovery; when reporting to Sentry
use Sentry.captureException(error) together with Sentry.captureContext (or
Sentry.setContext) to tag the event with error.digest for correlation (ensure
you pass error.digest in the context before captureException) so production logs
can be tied to the UI error digest.
🧹 Nitpick comments (1)
apps/docs/src/instrumentation.ts (1)
1-13: Useelse ifto clarify mutually exclusive runtime branches.Since
NEXT_RUNTIMEis mutually exclusive, switching toelse ifmakes the intent clearer and avoids unnecessary condition checks:Runtime branch tightening
export async function register() { if (process.env.NEXT_RUNTIME === "nodejs") { await import("../sentry.server.config"); - } - - if (process.env.NEXT_RUNTIME === "edge") { + } else if (process.env.NEXT_RUNTIME === "edge") { await import("../sentry.edge.config"); } }The direct assignment of
Sentry.captureRequestErrortoonRequestErroris correct and intentional for Next.js 16.1.1 with@sentry/nextjs10.38.0—Sentry explicitly documents this pattern as the recommended integration approach for error capture in instrumentation files.
| // This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on). | ||
| // The config you add here will be used whenever one of the edge features is loaded. | ||
| // Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally. | ||
| // https://docs.sentry.io/platforms/javascript/guides/nextjs/ | ||
|
|
||
| import * as Sentry from "@sentry/nextjs"; | ||
|
|
||
| Sentry.init({ | ||
| dsn: "https://e83ce4699e59051fdeaa330bf4a0dfb9@o4510879743737856.ingest.us.sentry.io/4510879744000000", | ||
|
|
||
| // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. | ||
| tracesSampleRate: 1, | ||
|
|
||
| // Enable logs to be sent to Sentry | ||
| enableLogs: true, | ||
|
|
||
| // Enable sending user PII (Personally Identifiable Information) | ||
| // https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii | ||
| sendDefaultPii: true, | ||
| }); |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
@sentry/nextjs edge runtime enableLogs support configuration
💡 Result:
enableLogs is supported in the Next.js Edge runtime, but you need a version of the Sentry JS SDK which includes the Edge logs export (added via PR #16166, merged Apr 30, 2025). In older versions you’ll see errors like “Export logger doesn’t exist in target module” when using Sentry.logger from middleware.ts. [1][2]
What to configure
1) Upgrade @sentry/nextjs to a release new enough to include that Edge export (post–Apr 30, 2025). [1][2]
2) Enable logs in your Edge init file (typically sentry.edge.config.ts/js created by the wizard):
// sentry.edge.config.ts
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.SENTRY_DSN,
enableLogs: true,
// optional:
// beforeSendLog: (log) => log,
});Sentry’s logging options are enableLogs and beforeSendLog (the older _experiments.enableLogs was deprecated in favor of the top-level options). [3][4]
3) Use the logger APIs from Edge code (middleware/edge routes):
import * as Sentry from "@sentry/nextjs";
Sentry.logger.info("edge request received");(These Sentry.logger APIs are what enableLogs turns on.) [4]
Sources:
[1] getsentry/sentry-javascript#16166
[2] getsentry/sentry-javascript#16151
[3] https://newreleases.io/project/npm/%40sentry/nextjs/release/9.41.0
[4] https://docs.sentry.io/platforms/javascript/guides/electron/logs
🌐 Web query:
Sentry sendDefaultPii what data included edge server runtime
💡 Result:
In Sentry’s JavaScript/Next.js SDKs (including Edge runtime), sendDefaultPii: true mainly affects whether the SDK will attach PII-related request/user data to events. Concretely, it enables (or allows integrations to enable):
- Cookies: the
CookieandSet-Cookieheaders can be captured (for fetch/XHR context). By default, cookies aren’t sent. [1] - User IP address: the SDK may send (or infer) the client IP (unless you explicitly set
ip_address: null). By default, IP isn’t sent. [1] - Logged-in user fields: user identifiers like email / user id / username may be attached if an integration (or your code) sets them; by default, user identity info isn’t sent. [1]
- Reminder for “Edge server runtime”: you still have to consider what the Edge platform actually exposes (for example, whether you can truly access the end-user IP vs. a proxy/CDN IP);
sendDefaultPiionly controls whether Sentry is allowed to include that data when available. [1]
Separately (not specific to sendDefaultPii), Sentry notes that user context automation is controlled by sendDefaultPii, and sensitive data can also end up in places like URLs/query strings, transaction names, breadcrumbs, and HTTP spans, so you may still need beforeSend / scrubbing. [2]
Security note: there was a vulnerability where enabling sendDefaultPii could allow sensitive headers (for example auth/cookie) to leak into traces in certain affected Sentry SDK versions; guidance is to upgrade @sentry/nextjs to 10.27.0+ (or keep sendDefaultPii off). [3]
Sources:
[1] Sentry Docs – “Data Collected” (JavaScript SDK) https://docs.sentry.io/platforms/javascript/guides/react/data-management/data-collected
[2] Sentry Docs – “Scrubbing Sensitive Data” (Next.js) https://docs.sentry.dev/platforms/javascript/guides/nextjs/data-management/sensitive-data/
[3] Snyk – CVE-2025-65944 / fix version guidance https://security.snyk.io/vuln/SNYK-JS-SENTRYNEXTJS-14105054
🏁 Script executed:
# Find Sentry config files in the codebase to understand the context
find . -type f -name "*.config.ts" -o -name "*sentry*" | head -20Repository: prisma/docs
Length of output: 283
🏁 Script executed:
# Find and check Sentry version in package.json
find . -name "package.json" -type f | xargs grep -l "@sentry/nextjs" | head -5Repository: prisma/docs
Length of output: 79
🏁 Script executed:
# Read the server config to verify consistency of concerns
cat apps/docs/sentry.server.config.tsRepository: prisma/docs
Length of output: 825
🏁 Script executed:
# Check the `@sentry/nextjs` version
cat apps/docs/package.json | grep -A 5 -B 5 "@sentry/nextjs"Repository: prisma/docs
Length of output: 444
🏁 Script executed:
# Verify release date of `@sentry/nextjs` 10.38.0 and check if enableLogs was available
npm view `@sentry/nextjs`@10.38.0 time published 2>/dev/null || echo "Checking via web"Repository: prisma/docs
Length of output: 19867
🌐 Web query:
@sentry/nextjs 10.38.0 enableLogs edge runtime support when available
💡 Result:
In @sentry/nextjs@10.38.0, Edge-runtime logging is supported via the Edge entrypoint re-exporting @sentry/vercel-edge (so any logging APIs exposed by @sentry/vercel-edge become available in Next.js middleware/edge routes). This is why you’ll see wording like “Edge runtime support when available.” [1]
Specifically, Sentry added the missing logs export for the Vercel Edge SDK (fixing the “Export logger doesn’t exist in target module” problem in Next.js Edge) in PR getsentry/sentry-javascript#16166. [2]
To enable it, use the (newer) top-level option:
Sentry.init({ enableLogs: true });(_experiments.enableLogs was deprecated in favor of enableLogs.) [3]
Sources
[1] @sentry/nextjs@10.38.0 package.json exports/deps (shows Edge entrypoint + @sentry/vercel-edge dep) (app.unpkg.com)
[2] PR adding logs export for Vercel Edge / Next.js Edge support (github.com)
[3] Deprecation note: _experiments.enableLogs → enableLogs (newreleases.io)
Citations:
- 1: https://app.unpkg.com/%40sentry/nextjs%4010.38.0/files/package.json?utm_source=openai
- 2: feat(vercel-edge): Add logs export getsentry/sentry-javascript#16166
- 3: https://newreleases.io/project/github/getsentry/sentry-javascript/release/9.41.0?utm_source=openai
🌐 Web query:
@sentry/nextjs 10.27.0 10.38.0 release date April 2025 changelog
💡 Result:
-
@sentry/nextjs / sentry-javascript
10.27.0release date: Nov 24, 2025 (GitHub release shows “24 Nov”; the related security advisory was published Nov 24, 2025 and lists 10.27.0 as the patched version). [1][2]- Next.js-relevant changelog items in 10.27.0:
fix(nextjs): universal random tunnel path support(#18257) [1]
- Next.js-relevant changelog items in 10.27.0:
-
@sentry/nextjs / sentry-javascript
10.38.0release date: Jan 29, 2026 (GitHub release shows “29 Jan”; Socket records “Package last updated on 29 Jan 2026”). [3][4]- Next.js-relevant changelog items in 10.38.0:
fix(nextjs): Turn off debugID injection if sourcemaps are explicitly disabled(#19010) [3]
- Next.js-relevant changelog items in 10.38.0:
-
About “April 2025”: these
10.27.0and10.38.0releases are not from April 2025 (they’re Nov 2025 and Jan 2026, respectively). [1][3]
Sources:
[1] GitHub release notes for 10.27.0 (getsentry/sentry-javascript) (github.com)
[2] GitHub Advisory DB entry (published Nov 24, 2025; patched in 10.27.0) (github.com)
[3] GitHub release notes for 10.38.0 (getsentry/sentry-javascript) (github.com)
[4] Socket package page showing 10.38.0 published / last updated on Jan 29, 2026 (socket.dev)
Citations:
- 1: https://github.com/getsentry/sentry-javascript/releases/tag/10.27.0
- 2: https://github.com/advisories/GHSA-6465-jgvq-jhgp?utm_source=openai
- 3: https://github.com/getsentry/sentry-javascript/releases/tag/10.38.0
- 4: https://socket.dev/npm/package/%40sentry/nextjs?utm_source=openai
Move Sentry edge config to environment-driven setup with safer defaults for production.
The hardcoded DSN, aggressive sampling, and PII exposure create deployment and compliance risks:
- Hardcoded DSN reduces flexibility across deploy environments
sendDefaultPii: trueexposes cookies, IP addresses, and user identifiers (email/id/username) unless explicitly scrubbed — a compliance concern if PII handling isn't documented or requiredtracesSampleRate: 1+enableLogs: truegenerate verbose telemetry that can be costly and noisy in production
Same issues exist in sentry.server.config.ts and should be addressed together.
Recommended approach: Move DSN, sampling rate, and PII flag to environment variables with production-safe defaults (sampling at 0.1, logs only in dev, PII off by default).
Example direction
Sentry.init({
- dsn: "https://e83ce4699e59051fdeaa330bf4a0dfb9@o4510879743737856.ingest.us.sentry.io/4510879744000000",
+ dsn: process.env.SENTRY_DSN,
- tracesSampleRate: 1,
- enableLogs: true,
- sendDefaultPii: true,
+ tracesSampleRate: Number(process.env.SENTRY_TRACES_SAMPLE_RATE ?? 0.1),
+ enableLogs: process.env.NODE_ENV !== "production",
+ sendDefaultPii: false,
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on). | |
| // The config you add here will be used whenever one of the edge features is loaded. | |
| // Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally. | |
| // https://docs.sentry.io/platforms/javascript/guides/nextjs/ | |
| import * as Sentry from "@sentry/nextjs"; | |
| Sentry.init({ | |
| dsn: "https://e83ce4699e59051fdeaa330bf4a0dfb9@o4510879743737856.ingest.us.sentry.io/4510879744000000", | |
| // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. | |
| tracesSampleRate: 1, | |
| // Enable logs to be sent to Sentry | |
| enableLogs: true, | |
| // Enable sending user PII (Personally Identifiable Information) | |
| // https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii | |
| sendDefaultPii: true, | |
| }); | |
| // This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on). | |
| // The config you add here will be used whenever one of the edge features is loaded. | |
| // Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally. | |
| // https://docs.sentry.io/platforms/javascript/guides/nextjs/ | |
| import * as Sentry from "@sentry/nextjs"; | |
| Sentry.init({ | |
| dsn: process.env.SENTRY_DSN, | |
| // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. | |
| tracesSampleRate: Number(process.env.SENTRY_TRACES_SAMPLE_RATE ?? 0.1), | |
| // Enable logs to be sent to Sentry | |
| enableLogs: process.env.NODE_ENV !== "production", | |
| // Enable sending user PII (Personally Identifiable Information) | |
| // https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii | |
| sendDefaultPii: false, | |
| }); |
🤖 Prompt for AI Agents
In `@apps/docs/sentry.edge.config.ts` around lines 1 - 20, Replace the hardcoded
Sentry configuration in Sentry.init: read dsn from an environment variable
(e.g., process.env.SENTRY_DSN) instead of the literal string, drive
tracesSampleRate from an env var with a safe production default (e.g.,
parseFloat(process.env.SENTRY_TRACES_SAMPLE_RATE) || 0.1), set enableLogs based
on NODE_ENV (true only in development), and set sendDefaultPii from an env var
defaulting to false (e.g., !!JSON.parse(process.env.SENTRY_SEND_DEFAULT_PII ||
"false")); apply the same env-driven changes to sentry.server.config.ts so both
edge and server configs use the same safe defaults.
| "use client"; | ||
|
|
||
| import * as Sentry from "@sentry/nextjs"; | ||
| import NextError from "next/error"; | ||
| import { useEffect } from "react"; | ||
|
|
||
| export default function GlobalError({ | ||
| error, | ||
| }: { | ||
| error: Error & { digest?: string }; | ||
| }) { | ||
| useEffect(() => { | ||
| Sentry.captureException(error); | ||
| }, [error]); | ||
|
|
||
| return ( | ||
| <html lang="en"> | ||
| <body> | ||
| {/* `NextError` is the default Next.js error page component. Its type | ||
| definition requires a `statusCode` prop. However, since the App Router | ||
| does not expose status codes for errors, we simply pass 0 to render a | ||
| generic error message. */} | ||
| <NextError statusCode={0} /> | ||
| </body> | ||
| </html> | ||
| ); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "package.json" -type f | head -5Repository: prisma/docs
Length of output: 179
🏁 Script executed:
cat package.json | grep -A 3 '"next":\|"@sentry/nextjs":'Repository: prisma/docs
Length of output: 37
🏁 Script executed:
fd global-error --type fRepository: prisma/docs
Length of output: 89
🏁 Script executed:
cat package.json | grep -E '"(next|@sentry)' | head -10Repository: prisma/docs
Length of output: 37
🏁 Script executed:
cat apps/docs/package.json | grep -E '"(next|@sentry)'Repository: prisma/docs
Length of output: 198
🌐 Web query:
Next.js 16 app/global-error.tsx best practices NextError component
💡 Result:
App Router (app/) best practices for global-error.tsx (Next.js 16)
- Use
app/global-error.tsxonly as the “root-layout fails” fallback (errors thrown fromapp/layout.tsx/app/template.tsxaren’t caught byapp/error.tsx). Keep a rootapp/error.tsxtoo for most runtime errors so your normal layout/branding still renders. [1][2] - Mark it as a Client Component: error boundaries must be Client Components (
'use client'). [1][3] - Include your own
<html>and<body>becauseglobal-error.tsxreplaces the root layout when active. Also ensure any global styles/fonts your error UI needs are available to it. [1][3] - Don’t use
metadata/generateMetadataexports inglobal-error.tsx; use React’s<title>instead if you need a title change. [3] - Use
reset()for recovery (e.g., “Try again” button) and consider loggingerror.digest(especially in production, where error details are intentionally stripped). [1][2]
Minimal template (recommended shape)
'use client'
import React from 'react'
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
// Optional: log error / error.digest to your monitoring
return (
<html>
<body>
<h2>Something went wrong</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
)
}About the “NextError” component
- In the App Router, the documented/idiomatic approach is
error.tsx+global-error.tsxerror boundaries (not a “NextError component”). Next.js’s official guidance focuses on these file-convention boundaries. [1][2][3] - If you mean the legacy Pages Router
next/errordefault error UI, it’s generally not the recommended pattern for App Router; prefer the App Router boundaries above. [1][2]
Sources: Next.js Error Handling docs and file conventions for error / global-error. [1][2][3]
References:
[1] Next.js “Routing: Error Handling” (global errors, html/body requirement, reset)
[2] Next.js “Getting Started: Error Handling” (global-error example, production error forwarding/digest)
[3] Next.js “File Conventions: error.js” (global-error notes, metadata limitation, global styles/fonts)
🌐 Web query:
Sentry @sentry/nextjs 10.38.0 GlobalError error.digest tagging
💡 Result:
To get Next.js App Router error.digest into Sentry on @sentry/nextjs@10.38.0, you generally need to do it where Next.js actually gives you the digest: in your app/error.tsx and/or app/global-error.tsx error boundary component (they receive error: Error & { digest?: string }). Next.js documents that error.digest is a hash meant to correlate with server-side logs, and that in production server-component errors get a generic message plus digest. [1]
Recommended: tag it when you capture in global-error.tsx
// app/global-error.tsx
'use client';
import * as Sentry from '@sentry/nextjs';
import { useEffect } from 'react';
export default function GlobalError({
error,
}: {
error: Error & { digest?: string };
}) {
useEffect(() => {
Sentry.captureException(error, {
captureContext: {
tags: {
digest: error.digest,
},
},
});
}, [error]);
return (
<html>
<body>Something went wrong</body>
</html>
);
}This approach (capturing in the error boundary and adding a digest tag) is the one Sentry folks have recommended in practice. [2]
Why you may not see digest “globally” (for every event)
If you were trying to add it from beforeSend in server configs: for server-side events, the digest often isn’t available to the SDK because React/Next don’t expose it in a way Sentry can consistently access on the backend; a common conclusion is “you can’t really get it on the backend (beyond logs).” [3]
Sources:
[1] Next.js Error file convention docs (error.digest, global-error.tsx) https://nextjs.org/docs/app/api-reference/file-conventions/error
[2] Sentry JavaScript SDK discussion showing tagging digest from GlobalError getsentry/sentry-javascript#10071
[3] StackOverflow: digest not accessible on backend / via Sentry server hooks https://stackoverflow.com/questions/77761570/sentry-next-js-and-digest
🌐 Web query:
Next.js App Router global-error NextError vs custom error UI
💡 Result:
In the App Router, you generally don’t use next/error (or anything like a public “NextError” component) for runtime error UI. Instead, you create your own error boundaries via the special files:
app/<segment>/error.tsx: the normal way to show a custom fallback UI for errors that occur within that route segment (and its children). Errors bubble to the nearest parenterror.tsx, enabling granular handling. (nextjs.org)app/global-error.tsx: a catch-all boundary specifically to handle errors thrown in the rootapp/layout.tsx/app/template.tsx, because the rootapp/error.tsxwon’t catch errors thrown by the root layout itself. When active, it replaces the entire root layout, so it must render its own<html>and<body>. (nextjs.org)
So what about “NextError” vs custom UI?
- The built-in
Errorcomponent fromnext/erroris Pages Router–oriented (it’s documented under “Pages” routing) and is mainly for reusing the built-in Pages error page. It’s not the App Router pattern for error boundaries. (nextjs.org) - In the App Router, your error UI is your custom component in
error.tsx/global-error.tsx, which receives:error: Error & { digest?: string }reset: () => void(to retry rendering) (nextjs.org)
Practical guidance
- Create a root
app/error.tsxfor branded “something went wrong” UI inside your normal layout. - Add
app/global-error.tsxonly if you want a last-resort UI for failures in the root layout/template (and remember it can’t rely on layout-provided things like locale params because it replaces the layout tree). (nextjs.org) - Don’t expect detailed error messages in production: Next.js forwards only a generic
messageplus adigestfor correlating with server logs. (nextjs.org)
Citations:
- 1: https://nextjs.org/docs/app/building-your-application/routing/error-handling?utm_source=openai
- 2: https://nextjs.org/docs/14/app/building-your-application/routing/error-handling?utm_source=openai
- 3: https://nextjs.org/docs/pages/building-your-application/routing/custom-error?utm_source=openai
- 4: https://nextjs.org/docs/app/building-your-application/routing/error-handling?utm_source=openai
- 5: https://nextjs.org/docs/14/app/building-your-application/routing/error-handling?utm_source=openai
- 6: https://nextjs.org/docs/14/app/building-your-application/routing/error-handling?utm_source=openai
Replace NextError with custom error UI; add digest tagging and recovery mechanism.
The next/error component is Pages Router–only and not recommended for App Router. In Next.js 16 App Router, global-error.tsx should render your own minimal UI or a reusable error component, not NextError.
Additionally:
- Add
error.digesttagging viacaptureContextfor Sentry correlation with server logs (production mode hides detailed error messages, making the digest critical for debugging). - Destructure and use the
reset()function to provide a "Try again" recovery option.
Recommended pattern
'use client';
import * as Sentry from '@sentry/nextjs';
-import NextError from 'next/error';
import { useEffect } from 'react';
export default function GlobalError({
error,
+ reset,
}: {
error: Error & { digest?: string };
+ reset: () => void;
}) {
useEffect(() => {
- Sentry.captureException(error);
+ Sentry.captureException(error, {
+ captureContext: {
+ tags: {
+ digest: error.digest,
+ },
+ },
+ });
}, [error]);
return (
<html lang="en">
<body>
- {/* `NextError` is the default Next.js error page component. Its type
- definition requires a `statusCode` prop. However, since the App Router
- does not expose status codes for errors, we simply pass 0 to render a
- generic error message. */}
- <NextError statusCode={0} />
+ <h2>Something went wrong</h2>
+ <button onClick={() => reset()}>Try again</button>
</body>
</html>
);
}🤖 Prompt for AI Agents
In `@apps/docs/src/app/global-error.tsx` around lines 1 - 27, Replace the Pages
Router-only NextError usage in GlobalError with a minimal custom error UI and
recovery button: inside the GlobalError component (function GlobalError) remove
NextError and render a simple message and a "Try again" button that calls the
reset() function (destructure reset from the component props) to trigger
client-side recovery; when reporting to Sentry use
Sentry.captureException(error) together with Sentry.captureContext (or
Sentry.setContext) to tag the event with error.digest for correlation (ensure
you pass error.digest in the context before captureException) so production logs
can be tied to the UI error digest.
Summary by CodeRabbit