Error reporting (`see()`)
see (shipeasy error) is the structured error reporter. Every handled exception documents its product consequence, not just its stack. It works in vanilla JS…
Generated from the SDK's own /docs/ — also served raw at
https://shipeasy-ai.github.io/sdk/pages/error-reporting.md.
see (shipeasy error) is the structured error reporter. Every handled
exception documents its product consequence, not just its stack. It works
in vanilla JS on both sides — the whole grammar hangs off one import:
import { see } from "@shipeasy/sdk/client"; // or "@shipeasy/sdk/server"Report a handled exception — see(e)
try {
await submitOrder(order);
} catch (e) {
see(e).causes_the("checkout").to("use cached prices").extras({ order_id: order.id });
}The chain dispatches on the next microtask — no .send(). It ships
immediately (sendBeacon in the browser, fire-and-forget fetch on the
server), spam-guarded by a 30s dedup window and a per-session cap.
Report a non-exception problem — see.Violation(name)
The name is a stable identifier (it participates in the issue fingerprint),
so put variable data in .extras(), never the name:
if (rows.length > LIMIT) {
see
.Violation("large query")
.causes_the("search results")
.to("be trimmed")
.extras({ rows: rows.length });
}Never use see.Violation() for a caught exception — you'd drop the stack. Pass
the caught Error to see() instead.
Mark expected control flow — see.ControlFlowException(e)
Document an expected exception and report nothing (auto-capture skips marked
errors). The reason must start with "because":
try {
return decodeFoo(blob);
} catch (e) {
see.ControlFlowException(e).because("because it wasn't an encoded Foo");
return decodeBar(blob);
}Where reports land
The Shipeasy errors primitive — fingerprint-grouped issues (open / resolved / ignored, regression auto-reopens) with a near-real-time occurrence timeseries.
Client auto-capture
The client SDK also auto-captures network failures (fetch network errors +
5xx) into the same primitive (autoCollect: { errors }, on by default) — each
names a specific endpoint and outcome. It deliberately does not blanket-
report uncaught exceptions or unhandled promise rejections (those carry no
actionable consequence). Code that knows the consequence reports it explicitly.
Rules
- If you don't know the consequence, don't catch the exception.
- You may
see()then re-throw — the re-thrown error links to its inner report as acaused_bychain instead of double-counting. - Never put PII or high-cardinality data in
extras. - A
see()call beforeconfigure()/shipeasy()warns and drops — it never throws.
i18n (translations)
This SDK ships full i18n. The TypeScript SDK is the reference implementation: it owns the browser loader, the SSR bootstrap of strings, and the i18n.t()…
Testing
For unit tests, swap the live configure() for configureForTesting() — a drop-in sibling with no network, ever (no SDK key required). It replaces the active…