@danieljvdm/dev-kit 1.0.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/package.json +1 -1
- package/skill-sources.jsonc +2 -33
- package/skill-sources.lock.json +15 -117
- package/skills/animate/LICENSE +21 -0
- package/skills/animate/NOTICE +10 -0
- package/skills/animate/SKILL.md +34 -0
- package/skills/animate/references/gestures.md +27 -0
- package/skills/animate/references/glossary.md +136 -0
- package/skills/animate/references/implementation.md +22 -0
- package/skills/animate/references/opportunities.md +18 -0
- package/skills/animate/references/principles.md +48 -0
- package/skills/animate/references/review.md +19 -0
- package/skills/cloudflare-workers/LICENSE +202 -0
- package/skills/cloudflare-workers/NOTICE +9 -0
- package/skills/cloudflare-workers/SKILL.md +26 -0
- package/skills/cloudflare-workers/references/durable-objects.md +68 -0
- package/skills/cloudflare-workers/references/sandbox.md +48 -0
- package/skills/cloudflare-workers/references/workers.md +63 -0
- package/skills/cloudflare-workers/references/wrangler.md +56 -0
- package/skills/design-ui/LICENSE +21 -0
- package/skills/design-ui/NOTICE +8 -0
- package/skills/design-ui/SKILL.md +29 -0
- package/skills/design-ui/references/appearance.md +22 -0
- package/skills/design-ui/references/components.md +33 -0
- package/skills/design-ui/references/exploration.md +50 -0
- package/skills/design-ui/references/libraries.md +39 -0
- package/skills/design-ui/references/themes.md +23 -0
- package/skills/dev-kit/SKILL.md +19 -38
- package/skills/dev-kit/references/cloudflare-worker-api.md +1 -1
- package/skills/dev-kit/references/skills.md +2 -2
- package/skills/effect-development/SKILL.md +27 -0
- package/skills/effect-development/agents/openai.yaml +4 -0
- package/skills/effect-development/references/api/index.md +32 -0
- package/skills/effect-development/references/api/schema-codecs.md +15 -0
- package/skills/{build-effect-apis/references → effect-development/references/api}/verification.md +10 -5
- package/skills/{effect-architecture-audit/SKILL.md → effect-development/references/architecture/index.md} +1 -6
- package/skills/{effect-atom-state/references → effect-development/references/atom}/effect-atom-client.md +8 -6
- package/skills/{effect-atom-state/references → effect-development/references/atom}/effect-atom-testing.md +7 -2
- package/skills/effect-development/references/atom/index.md +40 -0
- package/skills/{build-effect-clis/references → effect-development/references/cli}/entrypoints-and-testing.md +6 -2
- package/skills/effect-development/references/cli/index.md +39 -0
- package/skills/effect-development/references/setup.md +15 -0
- package/skills/open-pull-request/SKILL.md +10 -70
- package/skills/open-pull-request/references/evidence.md +22 -0
- package/skills/open-pull-request/references/explanation.md +21 -0
- package/skills/open-pull-request/references/publication.md +21 -0
- package/skills/sentry/LICENSE +202 -0
- package/skills/sentry/LICENSE-UPSTREAM +21 -0
- package/skills/sentry/NOTICE +14 -0
- package/skills/sentry/SKILL.md +33 -0
- package/skills/sentry/references/alert-payloads.md +105 -0
- package/skills/sentry/references/alerts.md +17 -0
- package/skills/sentry/references/artifacts.md +25 -0
- package/skills/sentry/references/auth-token.md +65 -0
- package/skills/sentry/references/concepts/ai-monitoring.md +131 -0
- package/skills/sentry/references/concepts/choosing-a-signal.md +78 -0
- package/skills/sentry/references/concepts/crons.md +50 -0
- package/skills/sentry/references/concepts/data-scrubbing.md +43 -0
- package/skills/sentry/references/concepts/errors.md +40 -0
- package/skills/sentry/references/concepts/logging.md +85 -0
- package/skills/sentry/references/concepts/metrics.md +49 -0
- package/skills/sentry/references/concepts/monitors.md +78 -0
- package/skills/sentry/references/concepts/profiling.md +38 -0
- package/skills/sentry/references/concepts/reduce-volume.md +49 -0
- package/skills/sentry/references/concepts/releases.md +43 -0
- package/skills/sentry/references/concepts/session-replay.md +35 -0
- package/skills/sentry/references/concepts/tracing.md +54 -0
- package/skills/sentry/references/concepts/user-feedback.md +36 -0
- package/skills/sentry/references/debug-artifacts/android.md +68 -0
- package/skills/sentry/references/debug-artifacts/apple.md +96 -0
- package/skills/sentry/references/debug-artifacts/dotnet.md +70 -0
- package/skills/sentry/references/debug-artifacts/flutter.md +65 -0
- package/skills/sentry/references/debug-artifacts/index.md +75 -0
- package/skills/sentry/references/debug-artifacts/javascript.md +94 -0
- package/skills/sentry/references/debug-artifacts/matching.md +73 -0
- package/skills/sentry/references/debug-artifacts/react-native.md +75 -0
- package/skills/sentry/references/first-error-setup.md +25 -0
- package/skills/sentry/references/instrumentation.md +30 -0
- package/skills/sentry/references/issues.md +32 -0
- package/skills/sentry/references/new-project.md +17 -0
- package/skills/sentry/references/otel-exporter.md +30 -0
- package/skills/sentry/references/release-workflow.md +31 -0
- package/skills/sentry/references/releases/ci-pipeline.md +214 -0
- package/skills/sentry/references/releases/index.md +93 -0
- package/skills/sentry/references/releases/suspect-commits.md +155 -0
- package/skills/sentry/references/releases/tagging.md +131 -0
- package/skills/sentry/references/releases/troubleshooting.md +67 -0
- package/skills/sentry/references/sdks/android/crons.md +305 -0
- package/skills/sentry/references/sdks/android/error-monitoring.md +800 -0
- package/skills/sentry/references/sdks/android/index.md +748 -0
- package/skills/sentry/references/sdks/android/integrations.md +48 -0
- package/skills/sentry/references/sdks/android/logging.md +374 -0
- package/skills/sentry/references/sdks/android/metrics.md +288 -0
- package/skills/sentry/references/sdks/android/profiling.md +397 -0
- package/skills/sentry/references/sdks/android/session-replay.md +406 -0
- package/skills/sentry/references/sdks/android/tracing.md +861 -0
- package/skills/sentry/references/sdks/browser/error-monitoring.md +861 -0
- package/skills/sentry/references/sdks/browser/index.md +714 -0
- package/skills/sentry/references/sdks/browser/logging.md +315 -0
- package/skills/sentry/references/sdks/browser/profiling.md +236 -0
- package/skills/sentry/references/sdks/browser/session-replay.md +586 -0
- package/skills/sentry/references/sdks/browser/tracing.md +561 -0
- package/skills/sentry/references/sdks/browser/user-feedback.md +354 -0
- package/skills/sentry/references/sdks/cloudflare/ai-monitoring.md +661 -0
- package/skills/sentry/references/sdks/cloudflare/crons.md +231 -0
- package/skills/sentry/references/sdks/cloudflare/durable-objects.md +381 -0
- package/skills/sentry/references/sdks/cloudflare/error-monitoring.md +329 -0
- package/skills/sentry/references/sdks/cloudflare/index.md +698 -0
- package/skills/sentry/references/sdks/cloudflare/logging.md +169 -0
- package/skills/sentry/references/sdks/cloudflare/nodejs-compat.md +134 -0
- package/skills/sentry/references/sdks/cloudflare/tracing.md +475 -0
- package/skills/sentry/references/sdks/cocoa/error-monitoring.md +394 -0
- package/skills/sentry/references/sdks/cocoa/index.md +497 -0
- package/skills/sentry/references/sdks/cocoa/logging.md +209 -0
- package/skills/sentry/references/sdks/cocoa/metrics.md +136 -0
- package/skills/sentry/references/sdks/cocoa/profiling.md +223 -0
- package/skills/sentry/references/sdks/cocoa/session-replay.md +257 -0
- package/skills/sentry/references/sdks/cocoa/tracing.md +524 -0
- package/skills/sentry/references/sdks/cocoa/user-feedback.md +310 -0
- package/skills/sentry/references/sdks/dotnet/crons.md +465 -0
- package/skills/sentry/references/sdks/dotnet/error-monitoring.md +1100 -0
- package/skills/sentry/references/sdks/dotnet/index.md +614 -0
- package/skills/sentry/references/sdks/dotnet/logging.md +556 -0
- package/skills/sentry/references/sdks/dotnet/metrics.md +229 -0
- package/skills/sentry/references/sdks/dotnet/profiling.md +296 -0
- package/skills/sentry/references/sdks/dotnet/tracing.md +897 -0
- package/skills/sentry/references/sdks/elixir/crons.md +371 -0
- package/skills/sentry/references/sdks/elixir/error-monitoring.md +335 -0
- package/skills/sentry/references/sdks/elixir/index.md +383 -0
- package/skills/sentry/references/sdks/elixir/logging.md +239 -0
- package/skills/sentry/references/sdks/elixir/tracing.md +233 -0
- package/skills/sentry/references/sdks/flutter/ecosystem-integrations.md +70 -0
- package/skills/sentry/references/sdks/flutter/error-monitoring.md +312 -0
- package/skills/sentry/references/sdks/flutter/index.md +728 -0
- package/skills/sentry/references/sdks/flutter/logging.md +387 -0
- package/skills/sentry/references/sdks/flutter/metrics.md +310 -0
- package/skills/sentry/references/sdks/flutter/profiling.md +214 -0
- package/skills/sentry/references/sdks/flutter/session-replay.md +308 -0
- package/skills/sentry/references/sdks/flutter/tracing.md +502 -0
- package/skills/sentry/references/sdks/go/crons.md +270 -0
- package/skills/sentry/references/sdks/go/error-monitoring.md +361 -0
- package/skills/sentry/references/sdks/go/index.md +324 -0
- package/skills/sentry/references/sdks/go/logging.md +354 -0
- package/skills/sentry/references/sdks/go/metrics.md +273 -0
- package/skills/sentry/references/sdks/go/profiling.md +46 -0
- package/skills/sentry/references/sdks/go/tracing.md +366 -0
- package/skills/sentry/references/sdks/index.md +41 -0
- package/skills/sentry/references/sdks/nestjs/ai-monitoring.md +410 -0
- package/skills/sentry/references/sdks/nestjs/crons.md +268 -0
- package/skills/sentry/references/sdks/nestjs/error-monitoring.md +729 -0
- package/skills/sentry/references/sdks/nestjs/index.md +699 -0
- package/skills/sentry/references/sdks/nestjs/logging.md +174 -0
- package/skills/sentry/references/sdks/nestjs/metrics.md +243 -0
- package/skills/sentry/references/sdks/nestjs/profiling.md +127 -0
- package/skills/sentry/references/sdks/nestjs/tracing.md +762 -0
- package/skills/sentry/references/sdks/nextjs/ai-monitoring.md +494 -0
- package/skills/sentry/references/sdks/nextjs/crons.md +383 -0
- package/skills/sentry/references/sdks/nextjs/error-monitoring.md +974 -0
- package/skills/sentry/references/sdks/nextjs/index.md +491 -0
- package/skills/sentry/references/sdks/nextjs/logging.md +381 -0
- package/skills/sentry/references/sdks/nextjs/metrics.md +411 -0
- package/skills/sentry/references/sdks/nextjs/profiling.md +403 -0
- package/skills/sentry/references/sdks/nextjs/session-replay.md +462 -0
- package/skills/sentry/references/sdks/nextjs/tracing.md +628 -0
- package/skills/sentry/references/sdks/node/ai-monitoring.md +303 -0
- package/skills/sentry/references/sdks/node/crons.md +432 -0
- package/skills/sentry/references/sdks/node/error-monitoring.md +1125 -0
- package/skills/sentry/references/sdks/node/index.md +942 -0
- package/skills/sentry/references/sdks/node/logging.md +380 -0
- package/skills/sentry/references/sdks/node/metrics.md +278 -0
- package/skills/sentry/references/sdks/node/profiling.md +373 -0
- package/skills/sentry/references/sdks/node/tracing.md +878 -0
- package/skills/sentry/references/sdks/php/ai-monitoring.md +310 -0
- package/skills/sentry/references/sdks/php/crons.md +265 -0
- package/skills/sentry/references/sdks/php/error-monitoring.md +626 -0
- package/skills/sentry/references/sdks/php/index.md +362 -0
- package/skills/sentry/references/sdks/php/laravel.md +542 -0
- package/skills/sentry/references/sdks/php/logging.md +242 -0
- package/skills/sentry/references/sdks/php/metrics.md +193 -0
- package/skills/sentry/references/sdks/php/profiling.md +115 -0
- package/skills/sentry/references/sdks/php/symfony.md +552 -0
- package/skills/sentry/references/sdks/php/tracing.md +516 -0
- package/skills/sentry/references/sdks/python/ai-monitoring.md +351 -0
- package/skills/sentry/references/sdks/python/crons.md +218 -0
- package/skills/sentry/references/sdks/python/error-monitoring.md +292 -0
- package/skills/sentry/references/sdks/python/index.md +361 -0
- package/skills/sentry/references/sdks/python/logging.md +234 -0
- package/skills/sentry/references/sdks/python/metrics.md +154 -0
- package/skills/sentry/references/sdks/python/profiling.md +120 -0
- package/skills/sentry/references/sdks/python/tracing.md +364 -0
- package/skills/sentry/references/sdks/react/error-monitoring.md +1607 -0
- package/skills/sentry/references/sdks/react/index.md +492 -0
- package/skills/sentry/references/sdks/react/logging.md +364 -0
- package/skills/sentry/references/sdks/react/profiling.md +322 -0
- package/skills/sentry/references/sdks/react/react-features.md +1272 -0
- package/skills/sentry/references/sdks/react/session-replay.md +1193 -0
- package/skills/sentry/references/sdks/react/tracing.md +1415 -0
- package/skills/sentry/references/sdks/react-native/error-monitoring.md +1481 -0
- package/skills/sentry/references/sdks/react-native/expo-config-plugin.md +45 -0
- package/skills/sentry/references/sdks/react-native/index.md +1030 -0
- package/skills/sentry/references/sdks/react-native/logging.md +444 -0
- package/skills/sentry/references/sdks/react-native/profiling.md +386 -0
- package/skills/sentry/references/sdks/react-native/session-replay.md +704 -0
- package/skills/sentry/references/sdks/react-native/tracing.md +1086 -0
- package/skills/sentry/references/sdks/react-native/user-feedback.md +815 -0
- package/skills/sentry/references/sdks/react-router-framework/error-monitoring.md +127 -0
- package/skills/sentry/references/sdks/react-router-framework/index.md +411 -0
- package/skills/sentry/references/sdks/react-router-framework/logging.md +66 -0
- package/skills/sentry/references/sdks/react-router-framework/profiling.md +57 -0
- package/skills/sentry/references/sdks/react-router-framework/react-router-framework-features.md +110 -0
- package/skills/sentry/references/sdks/react-router-framework/session-replay.md +67 -0
- package/skills/sentry/references/sdks/react-router-framework/tracing.md +96 -0
- package/skills/sentry/references/sdks/react-router-framework/user-feedback.md +71 -0
- package/skills/sentry/references/sdks/ruby/crons.md +184 -0
- package/skills/sentry/references/sdks/ruby/error-monitoring.md +248 -0
- package/skills/sentry/references/sdks/ruby/index.md +297 -0
- package/skills/sentry/references/sdks/ruby/logging.md +168 -0
- package/skills/sentry/references/sdks/ruby/metrics.md +196 -0
- package/skills/sentry/references/sdks/ruby/migration.md +321 -0
- package/skills/sentry/references/sdks/ruby/profiling.md +107 -0
- package/skills/sentry/references/sdks/ruby/tracing.md +388 -0
- package/skills/sentry/references/sdks/svelte/error-monitoring.md +456 -0
- package/skills/sentry/references/sdks/svelte/index.md +467 -0
- package/skills/sentry/references/sdks/svelte/logging.md +344 -0
- package/skills/sentry/references/sdks/svelte/session-replay.md +369 -0
- package/skills/sentry/references/sdks/svelte/tracing.md +406 -0
- package/skills/sentry/references/sdks/tanstack-start/error-monitoring.md +149 -0
- package/skills/sentry/references/sdks/tanstack-start/index.md +381 -0
- package/skills/sentry/references/sdks/tanstack-start/logging.md +74 -0
- package/skills/sentry/references/sdks/tanstack-start/session-replay.md +76 -0
- package/skills/sentry/references/sdks/tanstack-start/tanstackstart-features.md +128 -0
- package/skills/sentry/references/sdks/tanstack-start/tracing.md +123 -0
- package/skills/sentry/references/sdks/tanstack-start/user-feedback.md +81 -0
- package/skills/sentry/references/search-query-language.md +226 -0
- package/skills/sentry/references/semantics/angular.md +7 -0
- package/skills/sentry/references/semantics/app.md +28 -0
- package/skills/sentry/references/semantics/art.md +17 -0
- package/skills/sentry/references/semantics/aws.md +43 -0
- package/skills/sentry/references/semantics/browser.md +34 -0
- package/skills/sentry/references/semantics/cache.md +12 -0
- package/skills/sentry/references/semantics/client.md +8 -0
- package/skills/sentry/references/semantics/cloud.md +12 -0
- package/skills/sentry/references/semantics/cloudflare.md +23 -0
- package/skills/sentry/references/semantics/code.md +11 -0
- package/skills/sentry/references/semantics/culture.md +11 -0
- package/skills/sentry/references/semantics/db.md +21 -0
- package/skills/sentry/references/semantics/device.md +43 -0
- package/skills/sentry/references/semantics/error.md +7 -0
- package/skills/sentry/references/semantics/event.md +8 -0
- package/skills/sentry/references/semantics/exception.md +10 -0
- package/skills/sentry/references/semantics/faas.md +19 -0
- package/skills/sentry/references/semantics/file.md +8 -0
- package/skills/sentry/references/semantics/flag.md +7 -0
- package/skills/sentry/references/semantics/gcp.md +16 -0
- package/skills/sentry/references/semantics/gen_ai.md +53 -0
- package/skills/sentry/references/semantics/general.md +11 -0
- package/skills/sentry/references/semantics/graphql.md +9 -0
- package/skills/sentry/references/semantics/grpc.md +19 -0
- package/skills/sentry/references/semantics/http.md +34 -0
- package/skills/sentry/references/semantics/index.md +63 -0
- package/skills/sentry/references/semantics/jsonrpc.md +8 -0
- package/skills/sentry/references/semantics/jvm.md +12 -0
- package/skills/sentry/references/semantics/koa.md +7 -0
- package/skills/sentry/references/semantics/logger.md +7 -0
- package/skills/sentry/references/semantics/mcp.md +37 -0
- package/skills/sentry/references/semantics/mdc.md +7 -0
- package/skills/sentry/references/semantics/messaging.md +23 -0
- package/skills/sentry/references/semantics/middleware.md +7 -0
- package/skills/sentry/references/semantics/navigation.md +9 -0
- package/skills/sentry/references/semantics/nel.md +11 -0
- package/skills/sentry/references/semantics/network.md +17 -0
- package/skills/sentry/references/semantics/os.md +15 -0
- package/skills/sentry/references/semantics/otel.md +10 -0
- package/skills/sentry/references/semantics/params.md +7 -0
- package/skills/sentry/references/semantics/process.md +14 -0
- package/skills/sentry/references/semantics/react.md +7 -0
- package/skills/sentry/references/semantics/remix.md +7 -0
- package/skills/sentry/references/semantics/resource.md +7 -0
- package/skills/sentry/references/semantics/rpc.md +10 -0
- package/skills/sentry/references/semantics/score.md +10 -0
- package/skills/sentry/references/semantics/sentry.md +69 -0
- package/skills/sentry/references/semantics/server.md +8 -0
- package/skills/sentry/references/semantics/service.md +8 -0
- package/skills/sentry/references/semantics/session.md +7 -0
- package/skills/sentry/references/semantics/state.md +7 -0
- package/skills/sentry/references/semantics/thread.md +8 -0
- package/skills/sentry/references/semantics/timber.md +7 -0
- package/skills/sentry/references/semantics/trpc.md +8 -0
- package/skills/sentry/references/semantics/ui.md +18 -0
- package/skills/sentry/references/semantics/url.md +15 -0
- package/skills/sentry/references/semantics/user.md +17 -0
- package/skills/sentry/references/semantics/user_agent.md +7 -0
- package/skills/sentry/references/semantics/vercel.md +42 -0
- package/skills/sentry/references/setup-verification.md +39 -0
- package/skills/sentry/references/snapshots/github-actions-fanout.md +206 -0
- package/skills/sentry/references/snapshots/github-actions-simple.md +102 -0
- package/skills/sentry/references/snapshots/github-actions-swift-snapshot-testing.md +118 -0
- package/skills/sentry/references/snapshots/index.md +19 -0
- package/skills/sentry/references/snapshots/snapshot-previews.md +100 -0
- package/skills/sentry/references/snapshots/snapshots.md +123 -0
- package/skills/sentry/references/snapshots/wizard-setup.md +134 -0
- package/skills/testing/LICENSE +21 -0
- package/skills/testing/NOTICE +7 -0
- package/skills/testing/SKILL.md +13 -19
- package/skills/testing/agents/openai.yaml +1 -2
- package/skills/testing/references/selection.md +23 -0
- package/skills/testing/references/tdd.md +19 -0
- package/skills/testing/references/test-design.md +17 -0
- package/src/catalog.ts +1 -7
- package/skills/build-effect-apis/SKILL.md +0 -81
- package/skills/build-effect-apis/agents/openai.yaml +0 -4
- package/skills/build-effect-clis/SKILL.md +0 -92
- package/skills/build-effect-clis/agents/openai.yaml +0 -4
- package/skills/effect-architecture-audit/agents/openai.yaml +0 -4
- package/skills/effect-atom-state/SKILL.md +0 -97
- package/skills/effect-atom-state/agents/openai.yaml +0 -4
- package/skills/effect-ts/SKILL.md +0 -35
- package/skills/effect-ts/agents/openai.yaml +0 -4
- /package/skills/{build-effect-apis/references → effect-development/references/api}/cloudflare-workers.md +0 -0
- /package/skills/{build-effect-apis/references → effect-development/references/api}/runtime-assembly.md +0 -0
- /package/skills/{build-effect-apis/references → effect-development/references/api}/server-and-middleware.md +0 -0
- /package/skills/{build-effect-apis/references → effect-development/references/api}/shared-contracts.md +0 -0
- /package/skills/{effect-architecture-audit/references → effect-development/references/architecture}/service-and-boundary-audit.md +0 -0
- /package/skills/{effect-atom-state/references → effect-development/references/atom}/effect-atom-lifecycle.md +0 -0
- /package/skills/{effect-atom-state/references → effect-development/references/atom}/effect-atom-workflows.md +0 -0
- /package/skills/{effect-atom-state/references → effect-development/references/atom}/tanstack-start.md +0 -0
- /package/skills/{build-effect-clis/references → effect-development/references/cli}/command-design.md +0 -0
- /package/skills/{build-effect-clis/references → effect-development/references/cli}/processes-and-platform.md +0 -0
|
@@ -0,0 +1,974 @@
|
|
|
1
|
+
# Error Monitoring — Sentry Next.js SDK
|
|
2
|
+
|
|
3
|
+
> Minimum SDK: `@sentry/nextjs` ≥8.0.0\
|
|
4
|
+
> `onRequestError` hook requires `@sentry/nextjs` ≥8.28.0 and Next.js 15+\
|
|
5
|
+
> `withServerActionInstrumentation` available since `@sentry/nextjs` ≥8.0.0
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Three-Runtime Architecture
|
|
10
|
+
|
|
11
|
+
Next.js runs code in three separate environments.
|
|
12
|
+
Sentry provides **distinct init files** for each:
|
|
13
|
+
|
|
14
|
+
| File | Runtime | Captures |
|
|
15
|
+
| --------------------------- | ------- | --------------------------------------------- |
|
|
16
|
+
| `instrumentation-client.ts` | Browser | Client-side errors, unhandled rejections |
|
|
17
|
+
| `sentry.server.config.ts` | Node.js | API routes, Server Components, Server Actions |
|
|
18
|
+
| `sentry.edge.config.ts` | Edge | Middleware, edge routes |
|
|
19
|
+
|
|
20
|
+
All three use the same DSN but are configured independently.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Automatic vs Manual Error Capture
|
|
25
|
+
|
|
26
|
+
### What Is Captured Automatically
|
|
27
|
+
|
|
28
|
+
| Error Type | Captured? | Mechanism |
|
|
29
|
+
| -------------------------------------------- | --------- | --------------------------------------------- |
|
|
30
|
+
| Unhandled client JS exceptions | ✅ Yes | `window.onerror` (GlobalHandlers integration) |
|
|
31
|
+
| Unhandled promise rejections (client) | ✅ Yes | `window.onunhandledrejection` |
|
|
32
|
+
| Server Component render errors (Next.js 15+) | ✅ Yes | `onRequestError` hook in `instrumentation.ts` |
|
|
33
|
+
| Unhandled API route crashes (server) | ✅ Yes | Node.js uncaught exception handler |
|
|
34
|
+
| Re-thrown errors from `try/catch` | ✅ Yes | Bubbles to global handler |
|
|
35
|
+
| `error.tsx` boundary errors | ❌ No | Next.js catches before Sentry |
|
|
36
|
+
| `global-error.tsx` boundary errors | ❌ No | Next.js catches before Sentry |
|
|
37
|
+
| Caught + swallowed `try/catch` errors | ❌ No | Must call `captureException` manually |
|
|
38
|
+
| Server Action graceful error returns | ❌ No | Must call `captureException` or use wrapper |
|
|
39
|
+
| Caught edge middleware errors | ❌ No | Must call `captureException` manually |
|
|
40
|
+
|
|
41
|
+
### The Core Rule
|
|
42
|
+
|
|
43
|
+
> **“If you catch an error and don’t re-throw it, Sentry never sees it.”**
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// ✅ Automatically captured — unhandled, bubbles up
|
|
47
|
+
throw new Error("Unhandled");
|
|
48
|
+
|
|
49
|
+
// ✅ Automatically captured — re-thrown
|
|
50
|
+
try {
|
|
51
|
+
await doSomething();
|
|
52
|
+
} catch (err) {
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ❌ NOT captured — swallowed by graceful return
|
|
57
|
+
try {
|
|
58
|
+
await doSomething();
|
|
59
|
+
} catch (err) {
|
|
60
|
+
return { error: "Failed" }; // ← must add captureException here
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ✅ Manually captured
|
|
64
|
+
try {
|
|
65
|
+
await doSomething();
|
|
66
|
+
} catch (err) {
|
|
67
|
+
Sentry.captureException(err);
|
|
68
|
+
return { error: "Failed" };
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Client-Side Error Capture
|
|
75
|
+
|
|
76
|
+
### `Sentry.captureException(error, context?)`
|
|
77
|
+
|
|
78
|
+
Captures an exception and sends it to Sentry.
|
|
79
|
+
Prefer `Error` objects — they include stack traces.
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// Basic
|
|
83
|
+
Sentry.captureException(new Error("Something broke"));
|
|
84
|
+
|
|
85
|
+
// With inline context (one-off enrichment)
|
|
86
|
+
Sentry.captureException(error, {
|
|
87
|
+
level: "fatal",
|
|
88
|
+
tags: { section: "checkout" },
|
|
89
|
+
extra: { orderId, userId: user.id },
|
|
90
|
+
user: { id: "user-123", email: "user@example.com" },
|
|
91
|
+
fingerprint: ["checkout-failure", String(error.code)],
|
|
92
|
+
contexts: {
|
|
93
|
+
cart: { items: 3, total: 99.99 },
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### `Sentry.captureMessage(message, levelOrContext?)`
|
|
99
|
+
|
|
100
|
+
Captures a plain message — useful for notable conditions that aren’t exceptions.
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// With severity level
|
|
104
|
+
Sentry.captureMessage("Deprecated API used", "warning");
|
|
105
|
+
// Levels: "fatal" | "error" | "warning" | "log" | "info" | "debug"
|
|
106
|
+
|
|
107
|
+
// With full context
|
|
108
|
+
Sentry.captureMessage("Payment method expired", {
|
|
109
|
+
level: "warning",
|
|
110
|
+
tags: { payment_provider: "stripe" },
|
|
111
|
+
user: { id: currentUser.id },
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Unhandled Rejections
|
|
116
|
+
|
|
117
|
+
Automatically captured by the `GlobalHandlers` integration.
|
|
118
|
+
To customize:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
// instrumentation-client.ts
|
|
122
|
+
Sentry.init({
|
|
123
|
+
dsn: "___PUBLIC_DSN___",
|
|
124
|
+
integrations: [
|
|
125
|
+
Sentry.globalHandlersIntegration({
|
|
126
|
+
onerror: true,
|
|
127
|
+
onunhandledrejection: true, // set false to handle manually
|
|
128
|
+
}),
|
|
129
|
+
],
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Manual rejection handling (if onunhandledrejection: false)
|
|
133
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
134
|
+
Sentry.captureException(event.reason);
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Error Boundaries
|
|
141
|
+
|
|
142
|
+
### App Router: `app/error.tsx` (Segment-level)
|
|
143
|
+
|
|
144
|
+
Each route segment can have its own `error.tsx`. Next.js catches these before Sentry —
|
|
145
|
+
you **must** call `captureException` manually inside `useEffect`.
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
// app/error.tsx (also: app/dashboard/error.tsx, etc.)
|
|
149
|
+
"use client";
|
|
150
|
+
|
|
151
|
+
import { useEffect } from "react";
|
|
152
|
+
import * as Sentry from "@sentry/nextjs";
|
|
153
|
+
|
|
154
|
+
export default function Error({
|
|
155
|
+
error,
|
|
156
|
+
reset,
|
|
157
|
+
}: {
|
|
158
|
+
error: Error & { digest?: string };
|
|
159
|
+
reset: () => void;
|
|
160
|
+
}) {
|
|
161
|
+
useEffect(() => {
|
|
162
|
+
// REQUIRED: Next.js catches this before Sentry can
|
|
163
|
+
Sentry.captureException(error);
|
|
164
|
+
}, [error]);
|
|
165
|
+
|
|
166
|
+
return (
|
|
167
|
+
<div>
|
|
168
|
+
<h2>Something went wrong!</h2>
|
|
169
|
+
<button onClick={() => reset()}>Try again</button>
|
|
170
|
+
</div>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
> **`digest`:** Server-side errors include a `digest` hash.
|
|
176
|
+
> Use it to correlate Sentry events with server logs.
|
|
177
|
+
|
|
178
|
+
### App Router: `app/global-error.tsx` (Root Layout)
|
|
179
|
+
|
|
180
|
+
Last-resort catch-all for root layout errors.
|
|
181
|
+
Must render its own `<html>` and `<body>`. Use the `NextError` component for consistency
|
|
182
|
+
with Next.js default error pages.
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
// app/global-error.tsx
|
|
186
|
+
"use client";
|
|
187
|
+
|
|
188
|
+
import * as Sentry from "@sentry/nextjs";
|
|
189
|
+
import NextError from "next/error";
|
|
190
|
+
import { useEffect } from "react";
|
|
191
|
+
|
|
192
|
+
export default function GlobalError({ error }: { error: Error & { digest?: string } }) {
|
|
193
|
+
useEffect(() => {
|
|
194
|
+
Sentry.captureException(error);
|
|
195
|
+
}, [error]);
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
<html>
|
|
199
|
+
<body>
|
|
200
|
+
{/*
|
|
201
|
+
App Router doesn't expose HTTP status codes for errors,
|
|
202
|
+
so pass 0 to render a generic error message.
|
|
203
|
+
*/}
|
|
204
|
+
<NextError statusCode={0} />
|
|
205
|
+
</body>
|
|
206
|
+
</html>
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### App Router: Error Boundary Directory Structure
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
app/
|
|
215
|
+
├── global-error.tsx # Root layout errors (last resort)
|
|
216
|
+
├── error.tsx # App-wide segment fallback
|
|
217
|
+
├── layout.tsx
|
|
218
|
+
├── page.tsx
|
|
219
|
+
└── dashboard/
|
|
220
|
+
├── error.tsx # Dashboard-specific error boundary
|
|
221
|
+
├── layout.tsx
|
|
222
|
+
└── page.tsx
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### React 18 and Earlier: `<Sentry.ErrorBoundary>`
|
|
226
|
+
|
|
227
|
+
For client components using React 18 or earlier, wrap with `<Sentry.ErrorBoundary>` for
|
|
228
|
+
additional control and fallback UIs:
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
"use client";
|
|
232
|
+
|
|
233
|
+
import * as Sentry from "@sentry/nextjs";
|
|
234
|
+
|
|
235
|
+
function CheckoutPage() {
|
|
236
|
+
return (
|
|
237
|
+
<Sentry.ErrorBoundary
|
|
238
|
+
fallback={({ error, resetError }) => (
|
|
239
|
+
<div>
|
|
240
|
+
<p>Checkout failed: {error.message}</p>
|
|
241
|
+
<button onClick={resetError}>Retry</button>
|
|
242
|
+
</div>
|
|
243
|
+
)}
|
|
244
|
+
beforeCapture={(scope, error) => {
|
|
245
|
+
scope.setTag("section", "checkout");
|
|
246
|
+
scope.setLevel("fatal");
|
|
247
|
+
}}
|
|
248
|
+
onError={(error, componentStack, eventId) => {
|
|
249
|
+
analytics.track("error_boundary", { eventId });
|
|
250
|
+
}}
|
|
251
|
+
>
|
|
252
|
+
<CheckoutFlow />
|
|
253
|
+
</Sentry.ErrorBoundary>
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### React 19+: `Sentry.reactErrorHandler()` with `createRoot`
|
|
259
|
+
|
|
260
|
+
React 19 exposes hooks on `createRoot`. If you’re using React 19 client components, pass
|
|
261
|
+
`Sentry.reactErrorHandler()` to each hook:
|
|
262
|
+
|
|
263
|
+
```tsx
|
|
264
|
+
// In your client entry point or root layout setup
|
|
265
|
+
import { createRoot } from "react-dom/client";
|
|
266
|
+
import * as Sentry from "@sentry/nextjs";
|
|
267
|
+
|
|
268
|
+
createRoot(container, {
|
|
269
|
+
onUncaughtError: Sentry.reactErrorHandler(), // fatal — tree unmounts
|
|
270
|
+
onCaughtError: Sentry.reactErrorHandler(), // caught by an ErrorBoundary
|
|
271
|
+
onRecoverableError: Sentry.reactErrorHandler(), // auto-recovery (hydration)
|
|
272
|
+
}).render(<App />);
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
> **Use both together:** `reactErrorHandler()` is the global net;
|
|
276
|
+
> `<Sentry.ErrorBoundary>` provides scoped fallback UIs.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Pages Router Error Handling
|
|
281
|
+
|
|
282
|
+
### `pages/_error.tsx`
|
|
283
|
+
|
|
284
|
+
Use `captureUnderscoreErrorException` — a helper that reads Next.js context and captures
|
|
285
|
+
the error with correct status code.
|
|
286
|
+
|
|
287
|
+
```tsx
|
|
288
|
+
// pages/_error.tsx
|
|
289
|
+
import * as Sentry from "@sentry/nextjs";
|
|
290
|
+
import type { NextPage } from "next";
|
|
291
|
+
import type { ErrorProps } from "next/error";
|
|
292
|
+
import Error from "next/error";
|
|
293
|
+
|
|
294
|
+
const CustomErrorComponent: NextPage<ErrorProps> = (props) => {
|
|
295
|
+
return <Error statusCode={props.statusCode} />;
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
CustomErrorComponent.getInitialProps = async (contextData) => {
|
|
299
|
+
// CRITICAL: await so Sentry flushes before the serverless function exits
|
|
300
|
+
await Sentry.captureUnderscoreErrorException(contextData);
|
|
301
|
+
return Error.getInitialProps(contextData);
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
export default CustomErrorComponent;
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### `pages/_app.tsx`
|
|
308
|
+
|
|
309
|
+
For global error handling at the app level in Pages Router:
|
|
310
|
+
|
|
311
|
+
```tsx
|
|
312
|
+
// pages/_app.tsx
|
|
313
|
+
import type { AppProps } from "next/app";
|
|
314
|
+
import * as Sentry from "@sentry/nextjs";
|
|
315
|
+
|
|
316
|
+
export default function MyApp({ Component, pageProps }: AppProps) {
|
|
317
|
+
return (
|
|
318
|
+
<Sentry.ErrorBoundary fallback={<p>An error has occurred.</p>}>
|
|
319
|
+
<Component {...pageProps} />
|
|
320
|
+
</Sentry.ErrorBoundary>
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Server-Side Error Capture
|
|
328
|
+
|
|
329
|
+
### `onRequestError` Hook (Next.js 15+, SDK ≥8.28.0)
|
|
330
|
+
|
|
331
|
+
Export `onRequestError` from `instrumentation.ts` to automatically capture Server
|
|
332
|
+
Component errors without adding `captureException` everywhere:
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
// instrumentation.ts
|
|
336
|
+
import * as Sentry from "@sentry/nextjs";
|
|
337
|
+
|
|
338
|
+
export async function register() {
|
|
339
|
+
if (process.env.NEXT_RUNTIME === "nodejs") {
|
|
340
|
+
await import("./sentry.server.config");
|
|
341
|
+
}
|
|
342
|
+
if (process.env.NEXT_RUNTIME === "edge") {
|
|
343
|
+
await import("./sentry.edge.config");
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Automatically captures errors from Server Components, Middleware, and proxies
|
|
348
|
+
export const onRequestError = Sentry.captureRequestError;
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### API Routes (App Router)
|
|
352
|
+
|
|
353
|
+
Unhandled errors crash the request and are auto-captured.
|
|
354
|
+
Caught errors must be captured manually:
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
// app/api/users/route.ts
|
|
358
|
+
import { NextResponse } from "next/server";
|
|
359
|
+
import * as Sentry from "@sentry/nextjs";
|
|
360
|
+
|
|
361
|
+
export async function POST(request: Request) {
|
|
362
|
+
try {
|
|
363
|
+
const body = await request.json();
|
|
364
|
+
const user = await db.users.create(body);
|
|
365
|
+
return NextResponse.json(user, { status: 201 });
|
|
366
|
+
} catch (error) {
|
|
367
|
+
Sentry.captureException(error, {
|
|
368
|
+
tags: { route: "/api/users", method: "POST" },
|
|
369
|
+
});
|
|
370
|
+
return NextResponse.json({ error: "Failed to create user" }, { status: 500 });
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### API Routes (Pages Router)
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
// pages/api/users.ts
|
|
379
|
+
import type { NextApiRequest, NextApiResponse } from "next";
|
|
380
|
+
import * as Sentry from "@sentry/nextjs";
|
|
381
|
+
|
|
382
|
+
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
383
|
+
try {
|
|
384
|
+
const data = await fetchData();
|
|
385
|
+
res.status(200).json(data);
|
|
386
|
+
} catch (error) {
|
|
387
|
+
Sentry.captureException(error);
|
|
388
|
+
res.status(500).json({ error: "Internal server error" });
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Server Actions
|
|
394
|
+
|
|
395
|
+
#### Manual Pattern
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
// app/actions.ts
|
|
399
|
+
"use server";
|
|
400
|
+
|
|
401
|
+
import * as Sentry from "@sentry/nextjs";
|
|
402
|
+
|
|
403
|
+
export async function createPost(formData: FormData) {
|
|
404
|
+
try {
|
|
405
|
+
const post = await db.posts.create({
|
|
406
|
+
data: { title: formData.get("title") as string },
|
|
407
|
+
});
|
|
408
|
+
return { success: true, id: post.id };
|
|
409
|
+
} catch (error) {
|
|
410
|
+
// Graceful return swallows — must capture manually
|
|
411
|
+
Sentry.captureException(error);
|
|
412
|
+
return { success: false, error: "Failed to create post" };
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
#### `withServerActionInstrumentation` (Recommended)
|
|
418
|
+
|
|
419
|
+
Automatically instruments server actions with tracing, attaches form data, and connects
|
|
420
|
+
client/server traces:
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
// app/actions.ts
|
|
424
|
+
"use server";
|
|
425
|
+
|
|
426
|
+
import * as Sentry from "@sentry/nextjs";
|
|
427
|
+
import { headers } from "next/headers";
|
|
428
|
+
|
|
429
|
+
export async function submitForm(formData: FormData) {
|
|
430
|
+
return Sentry.withServerActionInstrumentation(
|
|
431
|
+
"submitForm",
|
|
432
|
+
{
|
|
433
|
+
headers: await headers(), // connects client and server traces
|
|
434
|
+
formData, // attaches form data to Sentry events
|
|
435
|
+
recordResponse: true, // includes response data
|
|
436
|
+
},
|
|
437
|
+
async () => {
|
|
438
|
+
// Errors thrown here are automatically captured
|
|
439
|
+
const result = await processForm(formData);
|
|
440
|
+
return { success: true, data: result };
|
|
441
|
+
},
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## Edge Runtime Error Capture
|
|
449
|
+
|
|
450
|
+
Edge runtime runs in Next.js middleware and edge API routes.
|
|
451
|
+
Initialize Sentry via `sentry.edge.config.ts`:
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
// sentry.edge.config.ts
|
|
455
|
+
import * as Sentry from "@sentry/nextjs";
|
|
456
|
+
|
|
457
|
+
Sentry.init({
|
|
458
|
+
dsn: "___PUBLIC_DSN___",
|
|
459
|
+
tracesSampleRate: 1.0,
|
|
460
|
+
// Note: Edge runtime has limited Node.js API access
|
|
461
|
+
// Some Node.js-specific integrations are not available
|
|
462
|
+
});
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
Errors in middleware are auto-captured via `onRequestError`. Caught errors require
|
|
466
|
+
manual capture:
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
// middleware.ts
|
|
470
|
+
import { NextResponse } from "next/server";
|
|
471
|
+
import type { NextRequest } from "next/server";
|
|
472
|
+
import * as Sentry from "@sentry/nextjs";
|
|
473
|
+
|
|
474
|
+
export function middleware(request: NextRequest) {
|
|
475
|
+
try {
|
|
476
|
+
// middleware logic
|
|
477
|
+
return NextResponse.next();
|
|
478
|
+
} catch (error) {
|
|
479
|
+
Sentry.captureException(error, {
|
|
480
|
+
tags: { runtime: "edge", path: request.nextUrl.pathname },
|
|
481
|
+
});
|
|
482
|
+
return NextResponse.next();
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
export const config = {
|
|
487
|
+
// Exclude tunnel route from middleware if using tunnelRoute in withSentryConfig
|
|
488
|
+
matcher: ["/((?!monitoring|_next/static|_next/image|favicon.ico).*)"],
|
|
489
|
+
};
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
## Scope Management
|
|
495
|
+
|
|
496
|
+
Sentry merges three scope layers before sending each event.
|
|
497
|
+
Later scopes override earlier ones:
|
|
498
|
+
|
|
499
|
+
```
|
|
500
|
+
Global → Isolation → Current → Event Sent
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### Global Scope
|
|
504
|
+
|
|
505
|
+
Applied to every event.
|
|
506
|
+
Use for universal data (app version, build ID):
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
Sentry.getGlobalScope().setTag("app_version", "2.1.0");
|
|
510
|
+
Sentry.getGlobalScope().setContext("build", { sha: process.env.VERCEL_GIT_COMMIT_SHA });
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### Isolation Scope
|
|
514
|
+
|
|
515
|
+
- **Server:** Forked per request — safe for per-request user data (no
|
|
516
|
+
cross-contamination)
|
|
517
|
+
- **Browser:** One per page load
|
|
518
|
+
|
|
519
|
+
All top-level `Sentry.setXxx()` methods write to the isolation scope:
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
// These are identical:
|
|
523
|
+
Sentry.setTag("my-tag", "my value");
|
|
524
|
+
Sentry.getIsolationScope().setTag("my-tag", "my value");
|
|
525
|
+
|
|
526
|
+
// Set user on login (persists for the current request/page):
|
|
527
|
+
Sentry.setUser({ id: "user-42", email: "user@example.com" });
|
|
528
|
+
|
|
529
|
+
// Clear user on logout:
|
|
530
|
+
Sentry.setUser(null);
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### `withScope` — Temporary Per-Capture Context
|
|
534
|
+
|
|
535
|
+
The primary tool for adding context to a single capture without affecting other events:
|
|
536
|
+
|
|
537
|
+
```typescript
|
|
538
|
+
Sentry.withScope((scope) => {
|
|
539
|
+
scope.setTag("operation", "bulk-delete");
|
|
540
|
+
scope.setLevel("warning");
|
|
541
|
+
scope.setUser({ id: order.userId });
|
|
542
|
+
scope.setContext("bulk", { count: items.length });
|
|
543
|
+
scope.addBreadcrumb({
|
|
544
|
+
category: "operation",
|
|
545
|
+
message: "Bulk delete started",
|
|
546
|
+
level: "info",
|
|
547
|
+
});
|
|
548
|
+
Sentry.captureException(deleteError);
|
|
549
|
+
});
|
|
550
|
+
// Tags/context above do NOT appear on subsequent events
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### Scope Decision Guide
|
|
554
|
+
|
|
555
|
+
| Goal | API |
|
|
556
|
+
| ------------------------------------------ | ------------------------------------------------------ |
|
|
557
|
+
| Data on ALL events (app version, build ID) | `Sentry.getGlobalScope().setTag(...)` |
|
|
558
|
+
| Current request/page-load data | `Sentry.setTag(...)` (isolation scope) |
|
|
559
|
+
| One specific capture only | `Sentry.withScope((scope) => { ... })` |
|
|
560
|
+
| Inline on a single event | Second arg to `captureException(err, { tags: {...} })` |
|
|
561
|
+
|
|
562
|
+
---
|
|
563
|
+
|
|
564
|
+
## Event Enrichment
|
|
565
|
+
|
|
566
|
+
### `setTag` / `setTags` (Searchable)
|
|
567
|
+
|
|
568
|
+
Tags are **indexed and searchable** — use them for filtering, grouping, and alerting.
|
|
569
|
+
|
|
570
|
+
- Key: max 32 chars, `a-zA-Z0-9_.:- ` (no spaces); Value: max 200 chars, no newlines
|
|
571
|
+
|
|
572
|
+
```typescript
|
|
573
|
+
Sentry.setTag("page_locale", "de-at");
|
|
574
|
+
Sentry.setTags({
|
|
575
|
+
payment_method: "stripe",
|
|
576
|
+
subscription_tier: "pro",
|
|
577
|
+
region: "eu-west-1",
|
|
578
|
+
});
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### `setContext` (Structured, Non-searchable)
|
|
582
|
+
|
|
583
|
+
Attaches arbitrary structured data visible in the issue detail view.
|
|
584
|
+
Not indexed or searchable.
|
|
585
|
+
|
|
586
|
+
```typescript
|
|
587
|
+
Sentry.setContext("checkout", {
|
|
588
|
+
step: "payment",
|
|
589
|
+
cart_items: 3,
|
|
590
|
+
total_usd: 99.99,
|
|
591
|
+
coupon_applied: "SAVE20",
|
|
592
|
+
});
|
|
593
|
+
|
|
594
|
+
// Clear a context:
|
|
595
|
+
Sentry.setContext("checkout", null);
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
> **Depth:** Normalized to 3 levels deep by default.
|
|
599
|
+
> The `type` key is reserved — don’t use it.
|
|
600
|
+
|
|
601
|
+
### `setUser` (User Identity)
|
|
602
|
+
|
|
603
|
+
```typescript
|
|
604
|
+
// On login
|
|
605
|
+
Sentry.setUser({
|
|
606
|
+
id: "user-42",
|
|
607
|
+
email: "jane@example.com",
|
|
608
|
+
username: "janedoe",
|
|
609
|
+
subscription: "pro", // arbitrary extra fields accepted
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
// On logout
|
|
613
|
+
Sentry.setUser(null);
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
### `setExtra` / `setExtras` (Arbitrary Debug Data)
|
|
617
|
+
|
|
618
|
+
Non-indexed supplementary data.
|
|
619
|
+
Prefer `setContext` for structured objects with meaningful names.
|
|
620
|
+
|
|
621
|
+
```typescript
|
|
622
|
+
Sentry.setExtra("raw_api_response", responseText);
|
|
623
|
+
Sentry.setExtras({
|
|
624
|
+
formData: { fieldA: "value1" },
|
|
625
|
+
processingStep: "validation",
|
|
626
|
+
retryCount: 3,
|
|
627
|
+
});
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
### Tags vs Context vs Extra
|
|
631
|
+
|
|
632
|
+
| Feature | Searchable? | Indexed? | Best For |
|
|
633
|
+
| ----------- | ------------ | -------- | -------------------------------------- |
|
|
634
|
+
| **Tags** | ✅ Yes | ✅ Yes | Filtering, grouping, alerting |
|
|
635
|
+
| **Context** | ❌ No | ❌ No | Structured debug info (nested objects) |
|
|
636
|
+
| **Extra** | ❌ No | ❌ No | Arbitrary debug values |
|
|
637
|
+
| **User** | ✅ Partially | ✅ Yes | User attribution and filtering |
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
641
|
+
## Breadcrumbs
|
|
642
|
+
|
|
643
|
+
### Automatic Breadcrumbs (Zero Config)
|
|
644
|
+
|
|
645
|
+
| Type | What’s Captured |
|
|
646
|
+
| ------------ | ---------------------------------------- |
|
|
647
|
+
| `ui.click` | DOM element clicks |
|
|
648
|
+
| `navigation` | URL changes, route transitions |
|
|
649
|
+
| `http` | XHR/fetch requests (URL, method, status) |
|
|
650
|
+
| `console` | `console.log`, `warn`, `error` |
|
|
651
|
+
|
|
652
|
+
### Manual Breadcrumbs
|
|
653
|
+
|
|
654
|
+
```typescript
|
|
655
|
+
Sentry.addBreadcrumb({
|
|
656
|
+
category: "auth",
|
|
657
|
+
message: "User authenticated",
|
|
658
|
+
level: "info",
|
|
659
|
+
data: { userId: "u_42", method: "oauth2" },
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
Sentry.addBreadcrumb({
|
|
663
|
+
type: "http",
|
|
664
|
+
category: "api.request",
|
|
665
|
+
message: "POST /api/orders",
|
|
666
|
+
level: "info",
|
|
667
|
+
data: {
|
|
668
|
+
url: "/api/orders",
|
|
669
|
+
method: "POST",
|
|
670
|
+
status_code: 422,
|
|
671
|
+
reason: "Validation failed",
|
|
672
|
+
},
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
Sentry.addBreadcrumb({
|
|
676
|
+
type: "navigation",
|
|
677
|
+
category: "navigation",
|
|
678
|
+
message: "User navigated to checkout",
|
|
679
|
+
data: { from: "/cart", to: "/checkout/payment" },
|
|
680
|
+
});
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
### Breadcrumb Properties
|
|
684
|
+
|
|
685
|
+
| Key | Type | Values |
|
|
686
|
+
| ----------- | ------ | ------------------------------------------------------------------------------------------------------------------ |
|
|
687
|
+
| `type` | string | `"default"` \| `"debug"` \| `"error"` \| `"info"` \| `"navigation"` \| `"http"` \| `"query"` \| `"ui"` \| `"user"` |
|
|
688
|
+
| `category` | string | Dot-notation: `"auth"`, `"ui.click"`, `"api.request"` |
|
|
689
|
+
| `message` | string | Human-readable description |
|
|
690
|
+
| `level` | string | `"fatal"` \| `"error"` \| `"warning"` \| `"log"` \| `"info"` \| `"debug"` |
|
|
691
|
+
| `timestamp` | number | Unix timestamp (auto-set if omitted) |
|
|
692
|
+
| `data` | object | Arbitrary key/value data |
|
|
693
|
+
|
|
694
|
+
### `beforeBreadcrumb` — Filter or Mutate
|
|
695
|
+
|
|
696
|
+
```typescript
|
|
697
|
+
Sentry.init({
|
|
698
|
+
beforeBreadcrumb(breadcrumb, hint) {
|
|
699
|
+
// Drop password field interactions
|
|
700
|
+
if (breadcrumb.category === "ui.click") {
|
|
701
|
+
if (hint?.event?.target?.type === "password") return null;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// Drop verbose console.debug in production
|
|
705
|
+
if (breadcrumb.category === "console" && breadcrumb.level === "debug") {
|
|
706
|
+
return null;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// Enrich fetch breadcrumbs
|
|
710
|
+
if (breadcrumb.category === "fetch" && hint?.response) {
|
|
711
|
+
breadcrumb.data = {
|
|
712
|
+
...breadcrumb.data,
|
|
713
|
+
responseStatus: hint.response.status,
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
return breadcrumb;
|
|
718
|
+
},
|
|
719
|
+
maxBreadcrumbs: 50, // default: 100
|
|
720
|
+
});
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
---
|
|
724
|
+
|
|
725
|
+
## `beforeSend` and Filtering Hooks
|
|
726
|
+
|
|
727
|
+
### `beforeSend` — Modify or Drop Error Events
|
|
728
|
+
|
|
729
|
+
Last chance to modify or discard events.
|
|
730
|
+
Runs after all event processors.
|
|
731
|
+
Return `null` to drop.
|
|
732
|
+
|
|
733
|
+
```typescript
|
|
734
|
+
Sentry.init({
|
|
735
|
+
beforeSend(event, hint) {
|
|
736
|
+
const error = hint.originalException;
|
|
737
|
+
|
|
738
|
+
// Drop non-Error rejections (e.g. cancelled requests)
|
|
739
|
+
if (error && !(error instanceof Error)) return null;
|
|
740
|
+
|
|
741
|
+
// Drop browser extension errors
|
|
742
|
+
const frames = event.exception?.values?.[0]?.stacktrace?.frames;
|
|
743
|
+
if (frames?.some((f) => f.filename?.includes("extension://"))) return null;
|
|
744
|
+
|
|
745
|
+
// Scrub PII
|
|
746
|
+
if (event.user?.email) {
|
|
747
|
+
event.user = { ...event.user, email: "[filtered]" };
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// Override fingerprint for known patterns
|
|
751
|
+
if (error?.name === "ChunkLoadError") {
|
|
752
|
+
event.fingerprint = ["chunk-load-failure"];
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
return event;
|
|
756
|
+
},
|
|
757
|
+
});
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
> **Note:** Only one `beforeSend` is allowed.
|
|
761
|
+
> For multiple processors, use `addEventProcessor()`.
|
|
762
|
+
|
|
763
|
+
### `beforeSendTransaction` — Modify or Drop Performance Events
|
|
764
|
+
|
|
765
|
+
```typescript
|
|
766
|
+
Sentry.init({
|
|
767
|
+
beforeSendTransaction(event) {
|
|
768
|
+
if (event.transaction === "/api/health") return null;
|
|
769
|
+
return event;
|
|
770
|
+
},
|
|
771
|
+
});
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
### `ignoreErrors` — Pattern-Based Filtering
|
|
775
|
+
|
|
776
|
+
```typescript
|
|
777
|
+
Sentry.init({
|
|
778
|
+
ignoreErrors: [
|
|
779
|
+
"ResizeObserver loop limit exceeded",
|
|
780
|
+
"fb_xd_fragment",
|
|
781
|
+
/^Network Error$/i,
|
|
782
|
+
/Loading chunk \d+ failed/,
|
|
783
|
+
/^Script error\.?$/,
|
|
784
|
+
],
|
|
785
|
+
});
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
### `allowUrls` / `denyUrls`
|
|
789
|
+
|
|
790
|
+
```typescript
|
|
791
|
+
Sentry.init({
|
|
792
|
+
// Only capture errors from your own scripts:
|
|
793
|
+
allowUrls: [/https?:\/\/((cdn|www)\.)?yourapp\.com/],
|
|
794
|
+
|
|
795
|
+
// Block third-party noise:
|
|
796
|
+
denyUrls: [/extensions\//i, /^chrome:\/\//i, /^moz-extension:\/\//i, /gtm\.js/],
|
|
797
|
+
});
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
---
|
|
801
|
+
|
|
802
|
+
## Fingerprinting and Custom Grouping
|
|
803
|
+
|
|
804
|
+
All events have a **fingerprint**. Events with the same fingerprint group into the same
|
|
805
|
+
issue.
|
|
806
|
+
|
|
807
|
+
### Per-Event Fingerprinting
|
|
808
|
+
|
|
809
|
+
```typescript
|
|
810
|
+
Sentry.captureException(error, {
|
|
811
|
+
fingerprint: ["checkout-failure", "stripe", String(error.code)],
|
|
812
|
+
});
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
### `withScope` Fingerprinting
|
|
816
|
+
|
|
817
|
+
```typescript
|
|
818
|
+
Sentry.withScope((scope) => {
|
|
819
|
+
scope.setFingerprint([method, path, String(err.statusCode)]);
|
|
820
|
+
Sentry.captureException(err);
|
|
821
|
+
});
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
### `beforeSend` Fingerprinting
|
|
825
|
+
|
|
826
|
+
```typescript
|
|
827
|
+
Sentry.init({
|
|
828
|
+
beforeSend(event, hint) {
|
|
829
|
+
const error = hint.originalException;
|
|
830
|
+
|
|
831
|
+
// All DatabaseConnectionErrors → one issue:
|
|
832
|
+
if (error instanceof DatabaseConnectionError) {
|
|
833
|
+
event.fingerprint = ["database-connection-error"];
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
// Extend default grouping (keep Sentry's stack-trace hash + add dimension):
|
|
837
|
+
if (error instanceof RPCError) {
|
|
838
|
+
event.fingerprint = [
|
|
839
|
+
"{{ default }}", // keep Sentry's default
|
|
840
|
+
String(error.functionName), // + split by RPC function
|
|
841
|
+
String(error.errorCode),
|
|
842
|
+
];
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
return event;
|
|
846
|
+
},
|
|
847
|
+
});
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
### Template Variables
|
|
851
|
+
|
|
852
|
+
| Variable | Description |
|
|
853
|
+
| ------------------- | ------------------------------------------------------------ |
|
|
854
|
+
| `{{ default }}` | Sentry’s normally computed hash (extend rather than replace) |
|
|
855
|
+
| `{{ transaction }}` | Current transaction name |
|
|
856
|
+
| `{{ function }}` | Top function in stack trace |
|
|
857
|
+
| `{{ type }}` | Exception type |
|
|
858
|
+
|
|
859
|
+
---
|
|
860
|
+
|
|
861
|
+
## Event Processors
|
|
862
|
+
|
|
863
|
+
Unlike `beforeSend` (only one allowed), you can register multiple event processors:
|
|
864
|
+
|
|
865
|
+
```typescript
|
|
866
|
+
// Global — runs for all events
|
|
867
|
+
Sentry.addEventProcessor((event, hint) => {
|
|
868
|
+
event.extra = {
|
|
869
|
+
...event.extra,
|
|
870
|
+
buildId: process.env.VERCEL_GIT_COMMIT_SHA,
|
|
871
|
+
};
|
|
872
|
+
return event;
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
// Scoped — runs only inside the withScope callback
|
|
876
|
+
Sentry.withScope((scope) => {
|
|
877
|
+
scope.addEventProcessor((event) => {
|
|
878
|
+
event.tags = { ...event.tags, processed_by: "checkout_handler" };
|
|
879
|
+
return event;
|
|
880
|
+
});
|
|
881
|
+
Sentry.captureException(checkoutError);
|
|
882
|
+
});
|
|
883
|
+
```
|
|
884
|
+
|
|
885
|
+
**Execution order:** All `addEventProcessor()` processors run first, then `beforeSend`
|
|
886
|
+
runs last (guaranteed).
|
|
887
|
+
|
|
888
|
+
---
|
|
889
|
+
|
|
890
|
+
## Error Capture Quick Reference
|
|
891
|
+
|
|
892
|
+
### Scenario Coverage Table
|
|
893
|
+
|
|
894
|
+
| Scenario | Auto Captured? | Solution |
|
|
895
|
+
| ------------------------------------ | -------------- | ------------------------------------------------------- |
|
|
896
|
+
| Unhandled client JS exception | ✅ Yes | — |
|
|
897
|
+
| Unhandled promise rejection | ✅ Yes | — |
|
|
898
|
+
| Server Component error (Next.js 15+) | ✅ Yes | `onRequestError` hook |
|
|
899
|
+
| Unhandled API route crash | ✅ Yes | — |
|
|
900
|
+
| `app/error.tsx` boundary | ❌ No | `captureException` in `useEffect` |
|
|
901
|
+
| `app/global-error.tsx` | ❌ No | `captureException` in `useEffect` |
|
|
902
|
+
| `try/catch` with graceful return | ❌ No | `captureException` before return |
|
|
903
|
+
| `try/catch` with re-throw | ✅ Yes | — |
|
|
904
|
+
| Server Action graceful error | ❌ No | `captureException` or `withServerActionInstrumentation` |
|
|
905
|
+
| Caught edge middleware error | ❌ No | `captureException` manually |
|
|
906
|
+
|
|
907
|
+
### API Quick Reference
|
|
908
|
+
|
|
909
|
+
```typescript
|
|
910
|
+
// ── Capture ───────────────────────────────────────────────────────────
|
|
911
|
+
Sentry.captureException(error)
|
|
912
|
+
Sentry.captureException(error, { level, tags, extra, contexts, fingerprint, user })
|
|
913
|
+
Sentry.captureMessage("text", "warning")
|
|
914
|
+
Sentry.captureMessage("text", { level, tags, extra })
|
|
915
|
+
|
|
916
|
+
// ── Next.js Specific ──────────────────────────────────────────────────
|
|
917
|
+
export const onRequestError = Sentry.captureRequestError // instrumentation.ts
|
|
918
|
+
await Sentry.captureUnderscoreErrorException(contextData) // pages/_error.tsx
|
|
919
|
+
Sentry.withServerActionInstrumentation("name", opts, fn) // server actions
|
|
920
|
+
|
|
921
|
+
// ── User ──────────────────────────────────────────────────────────────
|
|
922
|
+
Sentry.setUser({ id, email, username, ...custom })
|
|
923
|
+
Sentry.setUser(null) // clear on logout
|
|
924
|
+
|
|
925
|
+
// ── Tags (searchable) ─────────────────────────────────────────────────
|
|
926
|
+
Sentry.setTag("key", "value")
|
|
927
|
+
Sentry.setTags({ key1: "v1", key2: "v2" })
|
|
928
|
+
|
|
929
|
+
// ── Context (structured, non-searchable) ──────────────────────────────
|
|
930
|
+
Sentry.setContext("name", { key: value })
|
|
931
|
+
Sentry.setContext("name", null) // clear
|
|
932
|
+
|
|
933
|
+
// ── Extra (arbitrary) ─────────────────────────────────────────────────
|
|
934
|
+
Sentry.setExtra("key", anyValue)
|
|
935
|
+
Sentry.setExtras({ key1: v1 })
|
|
936
|
+
|
|
937
|
+
// ── Breadcrumbs ───────────────────────────────────────────────────────
|
|
938
|
+
Sentry.addBreadcrumb({ type, category, message, level, data })
|
|
939
|
+
|
|
940
|
+
// ── Scopes ────────────────────────────────────────────────────────────
|
|
941
|
+
Sentry.withScope((scope) => { scope.setTag(...); Sentry.captureException(...) })
|
|
942
|
+
Sentry.withIsolationScope((scope) => { ... })
|
|
943
|
+
Sentry.getGlobalScope().setTag(...)
|
|
944
|
+
Sentry.getIsolationScope().setTag(...) // same as Sentry.setTag()
|
|
945
|
+
|
|
946
|
+
// ── Fingerprinting ────────────────────────────────────────────────────
|
|
947
|
+
scope.setFingerprint(["group-key"])
|
|
948
|
+
event.fingerprint = ["{{ default }}", "extra-dimension"] // in beforeSend
|
|
949
|
+
|
|
950
|
+
// ── Hooks ─────────────────────────────────────────────────────────────
|
|
951
|
+
Sentry.init({ beforeSend(event, hint) { return event | null } })
|
|
952
|
+
Sentry.init({ beforeSendTransaction(event) { return event | null } })
|
|
953
|
+
Sentry.init({ beforeBreadcrumb(breadcrumb, hint) { return breadcrumb | null } })
|
|
954
|
+
Sentry.init({ ignoreErrors: ["string", /regex/] })
|
|
955
|
+
Sentry.init({ allowUrls: [/regex/] })
|
|
956
|
+
Sentry.init({ denyUrls: [/regex/] })
|
|
957
|
+
```
|
|
958
|
+
|
|
959
|
+
---
|
|
960
|
+
|
|
961
|
+
## Troubleshooting
|
|
962
|
+
|
|
963
|
+
| Issue | Solution |
|
|
964
|
+
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
965
|
+
| Errors not appearing from `error.tsx` | Add `Sentry.captureException(error)` in a `useEffect` — Next.js catches these before Sentry |
|
|
966
|
+
| Server Component errors missing | Ensure `export const onRequestError = Sentry.captureRequestError` is in `instrumentation.ts`; requires SDK ≥8.28.0 + Next.js 15 |
|
|
967
|
+
| Minified stack traces | Configure `authToken` in `withSentryConfig` for source map upload; use `digest` to correlate server logs with Sentry events |
|
|
968
|
+
| Duplicate errors | Check that only one handler captures the same error; in dev, React Strict Mode may double-fire — validate in production builds |
|
|
969
|
+
| Server Action errors missing | Use `withServerActionInstrumentation` wrapper or add `captureException` before any graceful `return` |
|
|
970
|
+
| Events blocked by ad-blockers | Set `tunnelRoute: "/monitoring"` in `withSentryConfig`; exclude the route from your middleware matcher |
|
|
971
|
+
| Missing edge errors | Verify `sentry.edge.config.ts` is imported via `instrumentation.ts` when `NEXT_RUNTIME === "edge"` |
|
|
972
|
+
| Turbopack source map issues | Turbopack source map upload support is experimental; fall back to webpack for production builds if maps are missing |
|
|
973
|
+
| Events from wrong DSN in hybrid app | All three runtimes (client, server, edge) use the same DSN; verify each init file has identical DSN value |
|
|
974
|
+
| `captureUnderscoreErrorException` not awaited | In Pages Router `_error.tsx`, always `await` it — serverless functions may exit before Sentry flushes otherwise |
|