Capture errors and enrich them with structured context so your team can diagnose production issues in seconds instead of hours. Covers captureException, captureMessage, scoped context (withScope / push_scope), breadcrumbs, custom fingerprinting, and beforeSend filtering using @sentry/node v8 and sentry-sdk v2 APIs.
Prerequisites
Sentry SDK installed and initialized (@sentry/node v8+ or sentry-sdk v2+)
A valid DSN configured via environment variable ()
SENTRY_DSN
Understanding of try/catch (JS) or try/except (Python) error handling
Use withScope (TypeScript) or push_scope (Python) to attach context to a single event without polluting the global scope. Context is automatically cleaned up when the scope exits.
TypeScript -- withScope
Sentry.withScope((scope) => {
// User identity for issue assignment and impact analysis
scope.setUser({
id: user.id,
email: user.email,
subscription: user.plan,
});
// Tags: indexed, searchable in Sentry UI filters
scope.setTag('payment_provider', 'stripe');
scope.setTag('feature', 'checkout');
// Structured context: visible in event detail sidebar
scope.setContext('payment', {
amount: 9999,
currency: 'USD',
customer_id: 'cus_abc123',
idempotency_key: 'idem_xyz789',
});
// Extra data: arbitrary key-value pairs for debugging
scope.setExtra('cart', cartItems);
// Override severity level
scope.setLevel('fatal');
// Custom fingerprint to control issue grouping
scope.setFingerprint(['checkout-failure', paymentProvider]);
Sentry.captureException(error);
});
// Scope is automatically cleaned up -- global scope unchanged
Python -- push_scope
with sentry_sdk.push_scope() as scope:
scope.user = {"id": user_id, "email": user_email}
scope.set_tag("feature", "checkout")
scope.set_extra("cart", cart_items)
scope.level = "fatal"
scope.fingerprint = ["checkout-failure", str(error_code)]
sentry_sdk.capture_exception(error)
# Scope is automatically cleaned up
Breadcrumbs
Breadcrumbs create a trail of events leading up to an error. Sentry auto-captures some (console logs, HTTP requests, DOM events), but manual breadcrumbs add domain-specific context.
TypeScript
Sentry.addBreadcrumb({
category: 'auth',
message: `User ${userId} logged in via ${provider}`,
level: 'info',
data: { provider, method: 'oauth2' },
});
Sentry.addBreadcrumb({
category: 'transaction',
message: 'Payment initiated',
level: 'info',
data: { amount: 49.99, items: 3 },
});
// The next captured error includes all breadcrumbs above
Override Sentry's default grouping to control how errors are merged into issues. Without custom fingerprints, Sentry groups by stack trace, which can split logically identical errors or merge unrelated ones.
// Group all timeout errors for /api/search into one issue
Sentry.withScope((scope) => {
scope.setFingerprint(['api-timeout', 'search-endpoint']);
Sentry.captureException(new Error('Search API timeout'));
});
// Group by error type + HTTP status + endpoint
Sentry.withScope((scope) => {
scope.setFingerprint(['http-error', String(response.status), endpoint]);
Sentry.captureException(error);
});
// Use {{ default }} to extend rather than replace default grouping
Sentry.withScope((scope) => {
scope.setFingerprint(['{{ default }}', tenantId]);
Sentry.captureException(error);
});
Global Filtering with beforeSend
Configure beforeSend during initialization to filter noise, scrub sensitive data, or enrich all events globally.
Sentry.init({
dsn: process.env.SENTRY_DSN,
beforeSend(event, hint) {
const error = hint?.originalException;
// Drop specific error types
if (error instanceof AbortError) return null;
if (error?.message?.match(/ResizeObserver loop/)) return null;
// Scrub sensitive headers
if (event.request?.headers) {
delete event.request.headers['Authorization'];
delete event.request.headers['Cookie'];
}
// Enrich database errors with subsystem tag
if (error instanceof DatabaseError) {
event.tags = { ...event.tags, subsystem: 'database' };
event.level = 'fatal';
}
return event; // Must return event or null
},
// Pattern-based noise filtering
ignoreErrors: [
'ResizeObserver loop',
'Non-Error promise rejection',
/Loading chunk \d+ failed/,
'Network request failed',
],
});
Output
Errors with full stack traces and context in the Sentry Issues dashboard
Scoped tags and structured context for filtering and search
Breadcrumb trails showing the user journey before errors
Custom fingerprints grouping related errors into single issues
Clean event stream via beforeSend filtering and ignoreErrors
Error Handling
Error
Cause
Solution
Missing stack trace
String passed instead of Error object
Always use new Error() or extend the Error class
Events not grouped properly
Default fingerprinting insufficient
Use scope.setFingerprint() with domain-specific keys
beforeSend dropping all events
Function returns undefined
Always return event or explicitly null
Scope leaking between requests
Global scope modified in async context
Use withScope() / push_scope() for per-request context
Too many events hitting quota
No filtering or sampling configured
Add ignoreErrors, beforeSend filters, or sampleRate
Context not showing in Sentry UI
Used setExtra for structured data
Use setContext('name', {...}) for sidebar visibility