@sentry/node
semver
>=7.0.0postconditions11functions8last verified2026-06-24coverage score73%Postconditions: what we check
- init · invalid-dsnwarningWhenDSN is missing, malformed, or contains an invalid public keyThrows
Error or DSN validation failure routed through onFatalErrorRequired handlingCaller MUST validate that the DSN env var (typically SENTRY_DSN) is present and non-empty before calling Sentry.init(). For optional telemetry — e.g. local dev — wrap in a try/catch and degrade gracefully (log a warning, continue without Sentry). DO NOT let an invalid DSN throw at module-load time during process boot — it will take down the whole app for a non-essential observability dependency.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - flush · flush-return-ignoredwarningWhenflush() return value is ignored — caller proceeds assuming successReturnsPromise<boolean> where false = timeout, events lostRequired handlingCaller MUST check the return value of await Sentry.flush(timeout). If false, events did not deliver within the timeout — log this fact (to stdout, not Sentry — Sentry is the thing that failed). Common mistake: writing `await Sentry.flush(2000); process.exit(0)` and assuming events landed. They didn't if flush returned false. For worker / serverless shutdown paths this is the difference between "lost the smoking-gun error log" and "captured the crash."costmediumin prodsilent failureusers seedegraded performancevisibilitysilent
- flush · flush-not-awaitederrorWhenProcess exits before queued Sentry events are sentReturnsPromise<boolean>Required handlingCaller MUST await Sentry.flush() (or Sentry.close()) before any deliberate process.exit() in worker / cron / serverless handlers. Fire-and-forget Sentry.captureException() does NOT block; events live in an in-memory queue that drains asynchronously. Exiting the process before drain completes drops the events.costmediumin prodsilent failureusers seedegraded performancevisibilitysilentSources[3]
- close · close-not-awaitederrorWhenProcess exits before close() resolves — same shape as flush-not-awaited but harder to retry because close() is one-shotReturnsPromise<boolean>Required handlingCaller MUST await Sentry.close(timeout) before deliberate process.exit() in shutdown handlers. Unlike flush(), close() disables future capture — calling captureException() after close() succeeds is a no-op (silent loss). Prefer flush() in long-running processes that just need to drain; reserve close() for true shutdown paths.costmediumin prodsilent failureusers seedegraded performancevisibilitysilentSources[3]
- startSpan · span-callback-rethrowswarningWhenErrors thrown inside the span callback are captured (good) AND re-thrown to the caller (caller must still handle)Throws
Whatever the callback threwRequired handlingCaller MUST treat Sentry.startSpan() as transparent for error propagation. The span captures the error for observability, but the error still escapes the span call and reaches the caller. If you want Sentry to "swallow" the error, wrap explicitly in try/catch — do not assume startSpan absorbs it. Common misuse: "I put it in a span so it's tracked" while the unhandled rejection crashes the process.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - startSpanManual · span-manual-finish-never-callederrorWhenfinish() or span.end() is never called — callback returns without ending the spanReturnsSpan remains open indefinitely — never sent to Sentry, never recordedRequired handlingCaller MUST call finish() (the second callback argument) or span.end() in ALL code paths including error paths. The most dangerous pattern is a try/catch that calls finish() only in the happy path — a thrown error exits the callback without finishing the span. Use try/finally: startSpanManual(options, (span, finish) => { try { doWork(); } finally { finish(); } }); Unfinished spans silently vanish: no performance data in Sentry, no error recorded, no alert fired. Debugging "why are my spans missing" is extremely difficult because no error is thrown.costlowin prodsilent failureusers seedegraded performancevisibilitysilentSources[5]
- startSpanManual · span-manual-callback-rethrowswarningWhenErrors thrown inside the startSpanManual callback are re-thrown to the caller (same as startSpan)Throws
Whatever the callback threwRequired handlingCaller MUST treat Sentry.startSpanManual() as transparent for error propagation. Errors are not swallowed. If the callback throws before calling finish(), the span is never ended AND the error propagates. Always use try/finally to guarantee finish() is called.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - startInactiveSpan · inactive-span-end-never-callederrorWhenspan.end() is never called — span was created but never finishedReturnsSpan remains open indefinitely — never sent to SentryRequired handlingCaller MUST call span.end() in ALL code paths. Wrap the work in try/finally to guarantee the span is ended even when errors are thrown: const span = Sentry.startInactiveSpan({ name: 'my-op' }); try { await doWork(); } finally { span.end(); } Because the span is inactive (not in async context), no automatic cleanup mechanism exists. An unended inactive span is permanently lost data — no error is thrown, no warning is logged.costlowin prodsilent failureusers seedegraded performancevisibilitysilentSources[5]
- withMonitor · monitor-callback-rethrowswarningWhenErrors thrown (or rejected Promises returned) by the withMonitor callback propagate to the caller after Sentry records the error check-inThrows
Whatever the callback threw or rejected withRequired handlingCaller MUST handle errors from Sentry.withMonitor() — the function does NOT swallow errors. The Sentry check-in (status="error") is sent before re-throwing, so the error IS captured by Sentry. But the cron handler code still needs its own try/catch to prevent unhandled rejections from crashing the worker/scheduler. Common mistake: wrapping the entire cron job in withMonitor and assuming that "Sentry handles it." Sentry records the failure; it does not recover from it. The scheduler will see the job as failed.costmediumin prodimmediate exceptionusers seedegraded performancevisibilityvisible - withMonitor · monitor-slug-not-configuredwarningWhenmonitorSlug does not match an existing monitor in the Sentry project, and upsertMonitorConfig is not provided to auto-create itReturnsCheck-ins are sent but silently ignored by Sentry — no monitor data recorded, no alerts firedRequired handlingAlways provide upsertMonitorConfig as the third argument to withMonitor() in production environments. The config creates the monitor if it does not exist, ensuring check-ins are recorded. Without it, a typo in the slug or a missing monitor setup causes complete silent loss of cron monitoring with no error thrown. Minimum config: Sentry.withMonitor('my-cron', callback, { schedule: { type: 'crontab', value: '0 * * * *' } });costmediumin prodsilent failureusers seedegraded performancevisibilitysilentSources[6]
- captureCheckIn · checkin-completion-missingwarningWhencaptureCheckIn({ status: 'in_progress' }) is called at job start but the completion check-in (status: 'ok' or 'error') is never sent — e.g., job crashes before the second captureCheckIn callReturnscheckInId (string) — but without the completion check-in, monitor marks run as timed out after maxRuntimeRequired handlingCaller MUST ensure the completion check-in is always sent, even when the job throws. Store the checkInId and wrap the job body in try/catch/finally: const checkInId = Sentry.captureCheckIn({ monitorSlug: 'my-cron', status: 'in_progress' }); try { await runJob(); Sentry.captureCheckIn({ monitorSlug: 'my-cron', status: 'ok', checkInId }); } catch (err) { Sentry.captureCheckIn({ monitorSlug: 'my-cron', status: 'error', checkInId }); throw err; } A missed completion check-in results in a "timed out" alert rather than an "error" alert — making root cause analysis harder.costlowin prodsilent failureusers seedegraded performancevisibilitysilentSources[6]
Sources
Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.
Official documentation
- [1]docs.sentry.io/platforms/javascript/guidesOptions
- [2]docs.sentry.io/platforms/javascript/guidesEmpty Dsn
- [3]docs.sentry.io/platforms/javascript/guidesDraining
- [4]docs.sentry.io/platforms/javascript/guidesSdk Initialization
- [5]docs.sentry.io/platforms/javascript/guidesCustom Instrumentation
- [6]docs.sentry.io/platforms/javascript/guidesCrons
Source code
- [7]github.com/getsentry/sentry-javascript/blobgetsentry/sentry-javascript · exports.ts
Need a different package?
Request a profile