Global unhandled promise rejection handler is configured
Why it matters
Unhandled promise rejections are silent killers. In Node.js prior to v15, they produced no output and leaked memory. In modern runtimes they terminate the process, causing unannounced restarts. In browsers, they leave background operations in an unknown state with no user feedback. CWE-703 (improper check for exceptional conditions) applies directly. Without a global handler, async errors from queued jobs, scheduled tasks, or deferred operations vanish entirely — producing outages with no trace in logs and no signal in error tracking.
Severity rationale
High because unhandled rejections terminate Node.js processes without warning or logging, causing unannounced service restarts with zero diagnostic trail.
Remediation
Register global rejection handlers in your app's entry point, before any async code runs. Both browser and Node.js surfaces need coverage.
// app/layout.tsx or lib/error-handlers.ts
if (typeof window !== 'undefined') {
window.addEventListener('unhandledrejection', (event) => {
// Send to error tracking before preventing default
reportError(event.reason)
event.preventDefault()
})
}
// server entry point
process.on('unhandledRejection', (reason) => {
logger.error({ reason }, 'Unhandled promise rejection')
// Do NOT exit — let the process continue unless reason is catastrophic
})
The handler must call into your error tracking service (Sentry, Datadog, etc.), not just console.error, for the check to pass.
Detection
-
ID:
unhandled-promise-rejection -
Severity:
high -
What to look for: Count all async operations (Promise chains, async/await) in the codebase. Enumerate which have .catch() or try/catch vs. which could produce unhandled rejections. Search for
window.onunhandledrejection(browser) orprocess.on('unhandledRejection')(Node.js). This handler should catch promise rejections that are not caught by.catch()ortry/catchand log them to an error tracking service. -
Pass criteria: An unhandled rejection handler is configured that logs rejections to an error tracking service or structured logging system. At least 1 global unhandled rejection handler must be registered, and at least 90% of async operations should have local error handling.
-
Fail criteria: No unhandled rejection handler found, or a handler exists but does not log to an error tracking service.
-
Skip (N/A) when: Never — unhandled rejections should always be handled.
-
Cross-reference: For window.onerror handling, see
window-onerror-handler. -
Detail on fail:
"No unhandledRejection handler configured. Promise rejections not caught by .catch() will be silently ignored"or"Handler exists but logs to console only, not to error tracking service" -
Remediation: Add an unhandled rejection handler in your app entry point:
// app/layout.tsx or lib/error-handlers.ts — global handler if (typeof window !== 'undefined') { window.addEventListener('unhandledrejection', (e) => { reportError(e.reason) }) }// For browser/client-side: window.addEventListener('unhandledrejection', (event) => { console.error('Unhandled promise rejection:', event.reason) // Send to error tracking service Sentry.captureException(event.reason) event.preventDefault() // Prevent app crash }) // For Node.js/server-side: process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled rejection at:', promise, 'reason:', reason) // Send to error tracking service logger.error({ reason, promise }, 'Unhandled rejection') })
External references
- cwe · CWE-703 — Improper Check or Handling of Exceptional Conditions
- iso-25010:2011 · reliability.fault-tolerance
Taxons
History
- 2026-04-18·v1.0.0·Initial import from error-resilience·automated