Crash reporting is on by default — unlike replay and body capture, the payload is data the SDK already holds (the exception plus the breadcrumb trail), fully redacted. It is a client veto, so you can switch it off:
init({ apiKey: 'txx_live_…', crashReporting: { disabled: true } });
What is caught
Two mechanisms:
mechanism | Fires on |
|---|---|
onerror | An uncaught exception. |
unhandledrejection | A promise rejection nobody handled. |
Both are page-global handlers, so they catch throws from anywhere on the page —
your framework’s render, an event handler, a third-party script. An error your
own code catches is handled and can be reported explicitly with captureException().
Report a caught exception
import { init } from '@traceitx/web';
const traceitx = init({
apiKey: 'txx_live_…',
appVersion: '2.4.0',
appBuild: 'web-abc123',
});
try {
await saveCart();
} catch (error) {
traceitx.captureException(error);
}
captureException(error: unknown): void reports a caught failure without opening
the reporter. It uses the existing redaction, user context, breadcrumbs, and
outbox. Returning does not confirm server receipt; queued reports use the normal
delivery retry path. It accepts Error objects and other thrown values.
Explicit reports use source: 'error', mechanism: 'captureException',
handled: true, and fatal: false. Global errors use handled: false and
fatal: false: an unhandled browser exception does not imply process termination.
Older SDK reports can omit fatal.
Both disabled: true and crashReporting.disabled: true suppress explicit
capture. Calls after kill() or destroy() are no-ops.
Set appBuild to identify the exact deployed build. It is stored as
context.app.build on errors and user-filed reports; appVersion remains the
release version. Source-map processing is not available yet.
What arrives
An unattended report is an ordinary envelope with its
top-level source set to error instead of manual — a web page survives an
uncaught error, so crash is reserved for the native SDKs’ process-terminating
case — plus a payload.crash block:
{
"exceptionType": "TypeError",
"message": "cart.lines is undefined",
"frames": [
{
"raw": "at renderCart (cart.js:42:11)",
"file": "cart.js",
"function": "renderCart",
"line": 42,
"col": 11
}
],
"mechanism": "onerror",
"handled": false,
"fatal": false,
"occurredAt": "2026-06-15T11:59:58.400Z",
"fingerprint": "9f2c1ab30d84e177"
}
Frames are raw — symbolication is not in v1, so a minified bundle produces minified frames. Keep your source maps; mapping happens on your side for now.
mechanism is a plain string, not an enum, so v2 can add values without older
receivers rejecting reports. Treat unknown values as opaque.
Grouping
fingerprint is 16 hex characters computed on the client from the exception type
and the top frames. It is a heuristic, deliberately — it means grouping works
with no server round-trip and no symbolication step. Two crashes sharing a
fingerprint are the same bug often enough to be useful for triage; treat it as a
strong hint, not an identity.
Duplicate reports and limits
Reporting the same error object through multiple capture paths creates one
report per SDK instance. The first accepted capture determines classification:
calling captureException(error) and then rethrowing that object leaves the
report marked handled.
Explicit and automatic capture have separate allowances. Each accepts one report per fingerprint and up to ten reports per SDK instance, so explicit reports cannot exhaust the automatic allowance. Different error objects with the same fingerprint can still be throttled; occurrence counts reflect received reports, not every failure. Retries keep the same report ID and do not add occurrences on the server. Automatic error breadcrumbs still record throttled errors.
What comes with it
An unattended report’s title is generated from the exception —
TypeError: cart.lines is undefined — and its description is empty; nobody
typed one. What makes it useful is everything else the SDK already had: the
breadcrumb trail leading to the throw, the
console and network breadcrumbs, the route, and
available session context. Error capture does not acquire a screenshot or attach
replay; it uses the context already buffered.
Errors your framework swallows
Vue’s errorHandler, Svelte’s error boundaries and Angular’s ErrorHandler all
catch errors before they reach window.onerror. Those never become unattended
reports automatically. Forward a caught error from inside that handler:
traceitx.captureException(err);
Or call traceitx.open() from there to put a human in the loop.