Error capture

Capture exceptions and unhandled rejections as $error events on the same pipeline as the rest of your traffic. Server-side capture is documented per-language on each SDK page; this page covers the browser-side opt-in and the wire shape that's common to all SDKs.

Paste to your agent

Wire error capture into this app
Enables auto-capture in the browser, adds a captureError() server-side wrap around the project's webhook / job handlers, and confirms the events land via the MCP errors tools.

Browser capture

The browser SDK exposes captureError() for manual capture and an init option for automatic capture of uncaught exceptions and unhandled promise rejections.

manual capture
import { captureError } from "@clamp-sh/analytics"

try {
  riskyOperation()
} catch (err) {
  captureError(err, { feature: "checkout", retry: 1 })
}

To auto-capture every uncaught exception and unhandled rejection:

auto-capture
import { init } from "@clamp-sh/analytics"

init("proj_xxx", { captureErrors: true })

The error-capture machinery lives in a separate chunk that lazy-loads on first use, so users who never enable it pay zero bytes for it.

Server-side capture

Each server SDK exposes its own captureError-style method. See the per-language page for the exact import and signature:

Event shape

Each captured error is a $error event with structured properties. Standard event fields (url, browser, OS, device_type, country, anonymous_id, session_id) are auto-populated by ingest the same way as any other event, so errors can be sliced by any traffic dimension.

$error event
{
  "name": "$error",
  "properties": {
    "error.message":     "Cannot read property 'foo' of undefined",
    "error.type":        "TypeError",
    "error.stack":       "TypeError: ...\n    at checkout.js:42:18\n    ...",
    "error.handled":     false,
    "error.fingerprint": "<server-computed sha256 prefix>"
  },
  "url":          "https://app.example.com/checkout",
  "browser":      "Safari",
  "os":           "iOS",
  "device_type":  "mobile",
  "country":      "DE",
  "anonymous_id": "anon_xxx",
  "session_id":   "ses_yyy",
  "timestamp":    "2026-05-01T12:34:56Z"
}

Fingerprint is computed server-side at ingest as a sha256 of the normalized error message plus the first stack frame (file:line). It groups the same bug across occurrences regardless of which session or SDK reported it. No source-map resolution today; production stacks are stored verbatim.

Length caps: error.stack up to 16KB, error.context up to 4KB, error.message up to 1KB. Other event property strings stay capped at 512 chars. Rate limit (browser only): up to 5 occurrences of the same message per session, then dropped. Server-side fingerprinting still groups across sessions.

Reading errors via MCP

Four MCP tools cover the questions an agent typically asks once errors are flowing.

errors.list

Recent error events with full context. One row per occurrence, newest first. Filter by message, fingerprint, browser, OS, device type, country, or handled flag.

errors.groups

Errors deduplicated by fingerprint, with count, users_affected, first_seen, and last_seen per group. Sort by count (default), users_affected, first_seen, or last_seen.

errors.timeline

Error count over time, hourly or daily buckets. Optionally scoped to one fingerprint to chart a single bug's rate.

errors.context

Breadcrumbs leading to one error: the events from the same session, before the error timestamp, in chronological order.

See MCP tools for full parameter details.

Plan

$error is a custom event, which requires a Pro or Growth plan to land in your charts. The browser SDK still installs the listeners on the free plan, but the events are dropped at ingest. See pricing for the per-plan event quotas.