Skip to content

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 throw inside a setTimeout/setInterval callback, a requestAnimationFrame frame, or a DOM/XHR event listener from a cross-origin script reaches window as a bare Script error. with no error object. This wraps those APIs to keep the original error, so GlobalErrorIntegration reports it with its full stack instead of dropping it.
  • ResourceErrorsIntegration — a broken <img>, <script>, or <link> fires an error event that carries no event.error and never bubbles, so GlobalErrorIntegration'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 on fetch/XHR throws no JS exception at all. This one doesn't call captureException() — it reports through log.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: ignoreErrors matches against the message (defaults to filtering out the browser's opaque "Script error."), denyUrls/allowUrls match 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.