Automatic capture
Uncaught exceptions and unhandled promise rejections are captured with no setup at all — as soon as init() runs (or the CDN script loads), GlobalErrorIntegration is already listening for the window's error and unhandledrejection events. It's the one integration on by default; everything else on this page is opt-in.
Capturing manually
Report a caught error yourself with captureException(). Any breadcrumbs added beforehand travel with it, giving you the trail of events that led up to the failure:
ts
Buglapse.addBreadcrumb({ type: 'ui.click', level: 'info', message: 'Clicked "Pay" button' })
try {
await pay()
} catch (error) {
Buglapse.captureException(error)
}captureException() only accepts an Error — if you catch something else (a string, a plain object thrown by a library), wrap it first: Buglapse.captureException(new Error(String(reason))).
Tagging a single capture
withScope() overlays tags/context for the duration of its callback only, without touching anything set globally via setTag()/setContext():
ts
Buglapse.withScope((scope) => {
scope.setTag('checkout.step', 'payment')
scope.setContext('order', { id: order.id, total: order.total })
try {
chargeCard(order)
} catch (error) {
Buglapse.captureException(error)
}
})The overlay only survives the synchronous portion of the callback — an await inside it loses the tags/context, since the browser client has no AsyncLocalStorage to carry it across. Capture before you await, or re-apply the tags with setTag()/setContext() on the client itself if the capture has to happen after one. See Tags & Context.
Catching errors that never reach window's handler
A few classes of failure never surface through GlobalErrorIntegration's error/ unhandledrejection listeners at all. Each of the integrations below closes one of those gaps, and — like every built-in — is toggled from the project's Settings → Loader Script tab if you're on the CDN embed, so no snippet change is needed to turn one on.
- BrowserApiErrorsIntegration — a
throwinside asetTimeout/setIntervalcallback, arequestAnimationFrameframe, or a DOM/XHR event listener from a cross-origin script reacheswindowas a bareScript error.with no error object. This wraps those APIs to keep the original error, soGlobalErrorIntegrationreports it with its full stack instead of dropping it. - ResourceErrorsIntegration — a broken
<img>,<script>, or<link>fires anerrorevent that carries noevent.errorand never bubbles, soGlobalErrorIntegration's bubble-phase listener misses it. This adds its own capture-phase listener for the same event. - HttpErrorsIntegration — a failed HTTP response (5xx by default, configurable via
statusThreshold) or a network/CORS failure onfetch/XHRthrows no JS exception at all. This one doesn't callcaptureException()— it reports throughlog.error()instead, so failed requests show up on the project's Logs page, not Exceptions.
Cutting down noise
Two integrations trim what gets sent, both applied before anything reaches the network:
- DedupeIntegration — drops an exception if it has the same name, message, and stack as the one captured immediately before it. It only compares against the last captured exception, not a full history, so the same error recurring after something else was captured in between still gets through.
- InboundFiltersIntegration — drops an exception by rule before it's sent:
ignoreErrorsmatches against the message (defaults to filtering out the browser's opaque"Script error."),denyUrls/allowUrlsmatch against the URL of the stack's top frame.
Both run client-side, before the quota is ever charged — an event either of these drops never counts against the project's daily usage.
How captured exceptions show up on the dashboard
Every captured exception lands on the project's Exceptions page individually, and is also grouped into an Issue — the dashboard computes a fingerprint from the event (name, message, stack, and any other field the project's fingerprint template references) and rolls repeat occurrences of the same error into one Issue, tracking its first/last seen time and a count instead of flooding the list with duplicates.
If you set a release (via data-release or init({ release })), it's stamped onto every exception and used to decode a minified stack trace back to original file/line/column once you've uploaded the matching sourcemaps — see Source maps.