npx skills add ...
npx skills add getsentry/sentry-for-claude --skill sentry-node-sdk
npx skills add getsentry/sentry-for-claude --skill sentry-node-sdk
Full Sentry SDK setup for Node.js, Bun, and Deno. Use when asked to "add Sentry to Node.js", "add Sentry to Bun", "add Sentry to Deno", "install @sentry/node", "@sentry/bun", or "@sentry/deno", or configure error monitoring, tracing, logging, profiling, metrics, crons, or AI monitoring for server-side JavaScript/TypeScript runtimes.
The same skill content is published under more than one repo. The install counts are split across them; any of these commands works.
All Skills > SDK Setup > Node.js / Bun / Deno SDK
Opinionated wizard that scans your project and guides you through complete Sentry setup for server-side JavaScript and TypeScript runtimes: Node.js, Bun, and Deno.
@sentry/node, @sentry/bun, or @sentry/denoinstrument.js, --import ./instrument.mjs, bun --preload, or npm:@sentry/denoNestJS? Use
sentry-nestjs-sdkinstead — it uses@sentry/nestjswith NestJS-native decorators and filters. Next.js? Usesentry-nextjs-sdkinstead — it handles the three-runtime architecture (browser, server, edge).
Note: SDK versions below reflect current Sentry docs at time of writing (
@sentry/node≥10.42.0,@sentry/bun≥10.42.0,@sentry/deno≥10.42.0). Always verify against docs.sentry.io/platforms/javascript/guides/node/ before implementing.
Run these commands to identify the runtime, framework, and existing Sentry setup:
What to determine:
| Question | Impact |
|---|---|
| Which runtime? (Node.js / Bun / Deno) | Determines package, init pattern, and preload flag |
| Node.js: ESM or CJS? | ESM requires --import ./instrument.mjs; CJS uses require("./instrument") |
| Framework detected? | Determines which error handler to register |
@sentry/* already installed? | Skip install, go straight to feature config |
instrument.js / instrument.mjs already exists? | Merge into it rather than overwrite |
| Logging library detected? | Recommend Sentry Logs |
| Cron / job scheduler detected? | Recommend Crons monitoring |
| AI library detected? | Recommend AI Monitoring |
| OpenTelemetry tracing detected? | Use OTLP path instead of native tracing |
| Companion frontend found? | Trigger Phase 4 cross-link |
Present a concrete recommendation based on what you found. Don't ask open-ended questions — lead with a proposal:
Route from OTel detection:
@opentelemetry/sdk-node or @opentelemetry/sdk-trace-node in package.json, or NodeTracerProvider in source) → use OTLP path: otlpIntegration() via @sentry/node-core/light; do not set tracesSampleRate; Sentry links errors to OTel traces automaticallyRecommended (core coverage):
Optional (enhanced observability):
Sentry.logger.*; recommend when winston/pino/bunyan or log search is needednodeRuntimeMetricsIntegration() (Node.js) / bunRuntimeMetricsIntegration() (Bun)Recommendation logic:
| Feature | Recommend when... |
|---|---|
| Error Monitoring | Always — non-negotiable baseline |
| OTLP Integration | OTel tracing detected — replaces native Tracing |
| Tracing | Always for server apps — HTTP spans + DB spans are high-value; skip if OTel tracing detected |
| Logging | App uses winston, pino, bunyan, or needs log-to-trace correlation |
| Profiling | Node.js only — performance-critical service; native addon compatible; skip if OTel tracing detected (requires tracesSampleRate, incompatible with OTLP) |
| AI Monitoring | App calls OpenAI, Anthropic, LangChain, Vercel AI, or Google GenAI |
| Crons | App uses node-cron, Bull, BullMQ, Agenda, or any scheduled task pattern |
| Metrics | App needs custom counters, gauges, or histograms |
| Runtime Metrics | Any Node.js or Bun service wanting automatic memory/CPU/event-loop visibility |
OTel tracing detected: "I see OpenTelemetry tracing in the project. I recommend Sentry's OTLP integration for tracing (via your existing OTel setup) + Error Monitoring + Sentry Logging [+ Metrics/Crons/AI Monitoring if applicable]. Shall I proceed?"
No OTel: "I recommend setting up Error Monitoring + Tracing. Want me to also add Logging or Profiling?"
You need to run this yourself — the wizard opens a browser for login and requires interactive input that the agent can't handle. Copy-paste into your terminal:
It handles login, org/project selection, SDK installation,
instrument.jscreation, and package.json script updates.Once it finishes, come back and skip to Verification.
If the user skips the wizard, proceed with Option 2 (Manual Setup) below.
CommonJS (instrument.js):
ESM (instrument.mjs):
CommonJS — add require("./instrument") as the very first line of your entry file:
ESM — use the --import flag so Sentry loads before all other modules (Node.js 18.19.0+ required):
Add to package.json scripts:
Or via environment variable (useful for wrapping existing start commands):
Register the Sentry error handler after all routes so it can capture framework errors:
Express:
Fastify:
Koa:
Hapi (async — must await):
Connect:
NestJS — has its own dedicated skill with full coverage:
Use the
sentry-nestjs-sdkskill instead. NestJS uses a separate package (@sentry/nestjs) with NestJS-native constructs:SentryModule.forRoot(),SentryGlobalFilter,@SentryTraced,@SentryCrondecorators, and GraphQL/Microservices support. Load that skill for complete NestJS setup.
Vanilla Node.js http module — wrap request handler manually:
Framework error handler summary:
| Framework | Function | Placement | Async? |
|---|---|---|---|
| Express | setupExpressErrorHandler(app) | After all routes | No |
| Fastify | setupFastifyErrorHandler(fastify) | Before routes | No |
| Koa | setupKoaErrorHandler(app) | First middleware | No |
| Hapi | setupHapiErrorHandler(server) | Before server.start() | Yes |
| Connect | setupConnectErrorHandler(app) | Before routes | No |
| NestJS | → Use sentry-nestjs-sdk | Dedicated skill | — |
No wizard available for Bun. Manual setup only.
instrument.ts (or instrument.js)--preloadAdd to package.json:
@sentry/bun automatically instruments Bun.serve() via JavaScript Proxy. No extra setup is required — just initialize with --preload and your Bun.serve() calls are traced:
Bun can run Express, Fastify, Hono, and Elysia. Use the same @sentry/bun import and the @sentry/node error handler functions (re-exported by @sentry/bun):
| Feature | Bun Support | Notes |
|---|---|---|
| Error Monitoring | ✅ Full | Same API as Node |
| Tracing | ✅ Via @sentry/node OTel | Most auto-instrumentations work |
| Logging | ✅ Full | enableLogs: true + Sentry.logger.* |
| Profiling | ❌ Not available | @sentry/profiling-node uses native addons incompatible with Bun |
| Metrics | ✅ Full | Sentry.metrics.* |
| Runtime Metrics | ✅ Full | bunRuntimeMetricsIntegration() — memory, CPU, event loop (no event loop delay percentiles) |
| Crons | ✅ Full | Sentry.withMonitor() |
| AI Monitoring | ✅ Full | OpenAI, Anthropic integrations work |
No wizard available for Deno. Manual setup only. Requires Deno 2.0+. Deno 1.x is not supported. Use
npm:specifier. Thedeno.land/x/sentryregistry is deprecated.
deno.json (Recommended)Or import directly with the npm: specifier:
Unlike Node.js and Bun, Deno does not have a
--preloador--importflag. Sentry must be the firstimportin your entry file.
The SDK requires network access to reach your Sentry ingest domain:
For development, --allow-all works but is not recommended for production.
Deno provides native cron scheduling. Use denoCronIntegration for automatic monitoring:
| Feature | Deno Support | Notes |
|---|---|---|
| Error Monitoring | ✅ Full | Unhandled exceptions + captureException |
| Tracing | ✅ Custom OTel | Automatic spans for Deno.serve() and fetch |
| Logging | ✅ Full | enableLogs: true + Sentry.logger.* |
| Profiling | ❌ Not available | No profiling addon for Deno |
| Metrics | ✅ Full | Sentry.metrics.* |
| Runtime Metrics | ❌ Not available | No runtime metrics integration for Deno |
| Crons | ✅ Full | denoCronIntegration() + Sentry.withMonitor() |
| AI Monitoring | ✅ Partial | Vercel AI SDK integration works; OpenAI/Anthropic via npm: |
Use this path only when OpenTelemetry tracing was detected in Phase 1 (e.g.,
@opentelemetry/sdk-nodeor@opentelemetry/sdk-trace-nodeinpackage.json). For projects without an existing OTel setup, use the standard@sentry/nodepath above.
The OTLP integration uses @sentry/node-core/light — a lightweight Sentry SDK that does not bundle its own OpenTelemetry. Instead, it hooks into the user's existing OTel TracerProvider and exports spans to Sentry via OTLP.
| Scenario | Recommended path |
|---|---|
| New project, no existing OTel | Standard @sentry/node (above) — includes built-in OTel |
| Existing OTel setup, want Sentry tracing | @sentry/node-core/light + otlpIntegration() |
| Existing OTel setup, sending to own Collector | @sentry/node-core/light + otlpIntegration({ collectorUrl }) |
The
@opentelemetry/*packages are peer dependencies. If the project already has them installed, skip duplicates.
With a custom Collector endpoint:
Same --import pattern as the standard Node.js setup:
@sentry/node| Aspect | @sentry/node (standard) | @sentry/node-core/light (OTLP) |
|---|---|---|
| OTel bundled | ✅ Yes — built-in TracerProvider | ❌ No — uses your existing provider |
| Tracing control | tracesSampleRate in Sentry.init() | OTel SDK controls sampling |
| Auto-instrumentation | ✅ Built-in (HTTP, DB, etc.) | ❌ You manage OTel instrumentations |
| Profiling | ✅ Available | ❌ Not compatible |
| Error ↔ trace linking | ✅ Automatic | ✅ Automatic (via otlpIntegration) |
| Package size | Larger (includes OTel) | Smaller (light mode) |
Load the corresponding reference file and follow its steps:
| Feature | Reference file | Load when... |
|---|---|---|
| Error Monitoring | references/error-monitoring.md | Always (baseline) — captures, scopes, enrichment, beforeSend |
| OTLP Integration | See OTLP Integration above | OTel tracing detected — replaces native Tracing |
| Tracing | references/tracing.md | OTel auto-instrumentation, custom spans, distributed tracing, sampling; skip if OTel tracing detected |
| Logging | references/logging.md | Structured logs, Sentry.logger.*, log-to-trace correlation |
| Profiling | references/profiling.md | Node.js only — CPU profiling, Bun/Deno gaps documented; skip if OTel tracing detected |
| Metrics | references/metrics.md | Custom counters, gauges, distributions |
| Runtime Metrics | See inline below | Automatic memory, CPU, and event loop metrics for Node.js and Bun |
| Crons | references/crons.md | Scheduled job monitoring, node-cron, Bull, Agenda, Deno.cron |
| AI Monitoring | Load sentry-setup-ai-monitoring skill | OpenAI, Anthropic, LangChain, Vercel AI, Google GenAI |
For each feature: read the reference file, follow its steps exactly, and verify before moving on.
Automatically collect Node.js and Bun runtime health metrics (memory, CPU utilization, event loop delay/utilization, uptime) at a configurable interval. Metrics appear in Sentry's Metrics product under the node.runtime.* / bun.runtime.* namespace.
Node.js — add nodeRuntimeMetricsIntegration() to your instrument.js:
Metrics collected by default: node.runtime.mem.rss, node.runtime.mem.heap_used, node.runtime.mem.heap_total, node.runtime.cpu.utilization, node.runtime.event_loop.delay.p50, node.runtime.event_loop.delay.p99, node.runtime.event_loop.utilization, node.runtime.process.uptime.
Bun — add bunRuntimeMetricsIntegration() to your instrument.ts:
Metrics collected: same as Node.js except no event loop delay percentiles (unavailable in Bun). Prefixed with bun.runtime.*.
Sentry.init() Core Options| Option | Type | Default | Notes |
|---|---|---|---|
dsn | string | — | Required. Also from SENTRY_DSN env var |
tracesSampleRate | number | — | 0–1; required to enable tracing; do not set when using OTLP path |
dataCollection | object | conservative unless set | Fine-grained control over auto-collected categories (userInfo, cookies, httpHeaders, httpBodies, queryParams, genAI). When omitted, the SDK falls back to sendDefaultPii (default false). Passing the object — even {} — flips unset categories to their permissive defaults; opt out per category. |
includeLocalVariables | boolean | false | Add local variable values to stack frames (Node.js) |
enableLogs | boolean | false | Enable Sentry Logs product (v9.41.0+) |
environment | string | "production" | Also from SENTRY_ENVIRONMENT env var |
release | string | — | Also from SENTRY_RELEASE env var |
debug | boolean | false | Log SDK activity to console |
enabled | boolean | true | Set false in tests to disable sending |
sampleRate | number | 1.0 | Fraction of error events to send (0–1) |
shutdownTimeout | number | 2000 | Milliseconds to flush events before process exit |
nativeNodeFetchIntegration() OptionsConfigures outgoing fetch/undici span capture. Since @opentelemetry/instrumentation-undici@0.22.0, response headers like content-length are no longer captured automatically — use headersToSpanAttributes to opt in:
| Option | Type | Default | Notes |
|---|---|---|---|
breadcrumbs | boolean | true | Record breadcrumbs for outgoing fetch requests |
headersToSpanAttributes.requestHeaders | string[] | — | Request header names to capture as span attributes |
headersToSpanAttributes.responseHeaders | string[] | — | Response header names to capture as span attributes |
otlpIntegration() Options (@sentry/node-core/light/otlp)For OTel-first projects using @sentry/node-core/light. Import: import { otlpIntegration } from '@sentry/node-core/light/otlp'.
| Option | Type | Default | Purpose |
|---|---|---|---|
setupOtlpTracesExporter | boolean | true | Auto-configure OTLP exporter to send spans to Sentry; set false if you already export to your own Collector |
collectorUrl | string | undefined | OTLP HTTP endpoint of an OTel Collector (e.g., http://localhost:4318/v1/traces); when set, spans are sent to the collector instead of the DSN-derived Sentry endpoint |
Flush buffered events before process exit — important for short-lived scripts and serverless:
| Variable | Purpose | Runtime |
|---|---|---|
SENTRY_DSN | DSN (alternative to hardcoding in init()) | All |
SENTRY_ENVIRONMENT | Deployment environment | All |
SENTRY_RELEASE | Release version string (auto-detected from git) | All |
SENTRY_AUTH_TOKEN | Source map upload token | Build time |
SENTRY_ORG | Org slug for source map upload | Build time |
SENTRY_PROJECT | Project slug for source map upload | Build time |
NODE_OPTIONS | Set --import ./instrument.mjs for ESM | Node.js |
Readable stack traces in production require uploading source maps with @sentry/cli or the webpack/esbuild/rollup plugins — for example, an inject + upload step in your build:
Upload needs a SENTRY_AUTH_TOKEN (a build-time secret). For creating the token and wiring it into CI, see sentry-source-maps.
After setup, verify Sentry is receiving events:
Or trigger an unhandled exception:
Then check your Sentry Issues dashboard — the error should appear within ~30 seconds.
Verification checklist:
| Check | How |
|---|---|
| Error captured | Throw in a handler, verify in Sentry Issues |
| Tracing working | Check Performance tab — should show HTTP spans |
includeLocalVariables working | Stack frame in Sentry should show variable values |
| Source maps working | Stack trace shows readable file names, not minified |
After completing backend setup, check for companion services:
If a frontend, framework-specific SDK, or other backend is found, suggest the matching skill:
Dedicated JavaScript framework skills (prefer these over generic node-sdk):
| Detected | Prefer skill | Why |
|---|---|---|
NestJS (@nestjs/core in package.json) | sentry-nestjs-sdk | Uses @sentry/nestjs with NestJS-native decorators, filters, and GraphQL support |
Next.js (next in package.json) | sentry-nextjs-sdk | Three-runtime architecture (browser, server, edge), withSentryConfig, source map upload |
Frontend companions:
| Detected | Suggest |
|---|---|
React app (react in package.json) | sentry-react-sdk |
| Svelte/SvelteKit | sentry-svelte-sdk |
Other backend companions:
| Detected | Suggest |
|---|---|
Go backend (go.mod) | sentry-go-sdk |
Python backend (requirements.txt, pyproject.toml) | sentry-python-sdk |
Ruby backend (Gemfile) | sentry-ruby-sdk |
Connecting frontend and backend with the same DSN or linked projects enables distributed tracing — stack traces that span your browser, API server, and database in a single trace view.
| Issue | Cause | Solution |
|---|---|---|
| Events not appearing | instrument.js loaded too late | Ensure it's the first require() / loaded via --import or --preload |
| Tracing spans missing | tracesSampleRate not set | Add tracesSampleRate: 1.0 to Sentry.init() |
| ESM instrumentation not working | Missing --import flag | Run with node --import ./instrument.mjs; import "./instrument.mjs" inside app is not sufficient |
@sentry/profiling-node install fails on Bun | Native addon incompatible | Profiling is not supported on Bun — remove @sentry/profiling-node |
| Deno: events not sent | Missing --allow-net permission | Run with --allow-net=o<ORG_ID>.ingest.sentry.io |
Deno: deno.land/x/sentry not working | Deprecated and frozen at v8.55.0 | Switch to npm:@sentry/deno specifier |
includeLocalVariables not showing values | Integration not activated or minified code | Ensure includeLocalVariables: true in init; check source maps |
| NestJS: errors not captured | Wrong SDK or missing filter | Use sentry-nestjs-sdk — NestJS needs @sentry/nestjs, not @sentry/node |
Hapi: setupHapiErrorHandler timing issue | Not awaited | Must await Sentry.setupHapiErrorHandler(server) before server.start() |
| Shutdown: events lost | Process exits before flush | Add await Sentry.close(2000) in SIGTERM/SIGINT handler |
| Stack traces show minified code | Source maps not uploaded | Configure @sentry/cli source map upload in build step |
| No traces appearing (OTLP) | Missing @opentelemetry/* packages or otlpIntegration not added | Verify @opentelemetry/sdk-trace-node is installed; add otlpIntegration() to integrations; do not set tracesSampleRate |
| OTLP: errors not linked to traces | otlpIntegration not registered | Ensure otlpIntegration() is in the integrations array — it registers the propagation context that links errors to OTel traces |
| Profiling not starting (OTLP) | Profiling requires tracesSampleRate | Profiling is not compatible with the OTLP path; use the standard @sentry/node setup instead |