@playstack/errors
Runtime-neutral error capture with scrubbing, trace correlation, grouping hints, and isolated backend fan-out.
Free. MIT licensed. Check preview availability before installing. See package access.
@playstack/errors reports operational failures without coupling application code to one monitoring vendor. One normalized, scrubbed event fans out to isolated structural drivers.
Install
npm install @playstack/core @playstack/errorsCompose the reporter
Initialize vendor SDKs in the application, adapt their clients, and construct one reporter for the lifecycle you control.
import { configureErrors } from '@playstack/errors'
import { sentry, sanitizeSentryEvent } from '@playstack/errors/sentry'
// In each application-owned Sentry initializer, including framework capture:
// beforeSend: (event) => sanitizeSentryEvent(event)
// If another beforeSend transforms events, sanitize its result LAST.
export const errors = configureErrors({
drivers: [sentry(initializedSentry)],
environment: process.env.DEPLOYMENT_ENVIRONMENT!,
release: process.env.RELEASE_ID!,
trace: activeTraceProvider,
onError: ({ stage, driverId, error }) => {
process.stderr.write(`Error reporting failure at ${stage}/${driverId}: ${String(error)}\n`)
},
})
errors.captureError(cause, {
severity: 'error',
tags: { feature: 'checkout' },
context: { attempt: 2 },
userId: user.id,
accountId: account.id,
fingerprint: ['checkout-submission'],
})captureError returns immediately and does not throw. Synchronous and asynchronous driver failures are sent to onError without stopping healthy drivers.
Reporter configuration
ConfigureErrorsOptions property | Type | Required | Purpose |
|---|---|---|---|
drivers | readonly ErrorDriver[] | Yes | One or more uniquely named delivery bridges. |
environment | string | Yes | Deployment environment attached to every event; maximum 64 characters. |
release | string | Yes | Release identifier attached to every event; maximum 200 characters. |
trace | ErrorTraceProvider | No | Supplies current W3C trace context when capture does not set it explicitly. |
onError | (failure) => void | No | Isolated observer for input, trace-provider, or driver failures. |
The reporter is instance-scoped. Create separate instances when SSR requests, tests, or applications in the same process require different configuration.
Capture properties
ErrorCaptureOptions property | Type | Purpose |
|---|---|---|
severity | debug | info | warning | error | fatal | Delivery severity; defaults to error. |
tags | Primitive record | Indexed, low-cardinality attributes. |
context | Primitive record | Non-indexed diagnostic attributes. |
userId | string | Opaque user attribution. |
accountId | string | Opaque account attribution. |
fingerprint | readonly string[] | Portable grouping hint; support depends on the driver. |
trace | ErrorTraceContext | null | Explicit W3C trace context, or null to suppress correlation. |
Tags and context allow at most 30 shallow primitive values. Private keys are dropped, while emails, bearer tokens, JWTs, credentials, and private assignments are redacted from strings, error messages, stacks, causes, trace state, and baggage.
Driver bridge
Implement this structural contract to connect another reporting backend:
interface ErrorDriver<TClient = unknown> {
id: string
client: TClient
capabilities: {
fingerprint: boolean
trace: false | 'native' | 'tag'
}
capture(event: CapturedErrorEvent): void | Promise<void>
}The id must be unique kebab case. client preserves access to vendor-specific behavior through errors.driver(id).client. Capabilities describe what the adapter actually guarantees; they do not emulate unsupported vendor features.
The package includes a structural Sentry adapter and basemarksErrorBridge at @playstack/errors/basemarks. The latter requires an application-owned captureError(error, normalizedEvent) transport; the published Basemarks web SDK does not implement that method. Neither bridge initializes an SDK. See Basemarks integration boundaries.
Sentry identity and final-event privacy
The adapter sends sanitized error data while retaining the original Error only as an identity hint for Sentry's duplicate suppression. Repeated native/direct/ framework captures can therefore share the SDK's original-object suppression; distinct Error objects remain distinct. Do not log or serialize that hint.
Install sanitizeSentryEvent as the last step of beforeSend in every SDK
runtime. Reporter scrubbing happens before inherited SDK scope and integrations
are merged, so it is not a substitute for this final hook. Preserve null from
an existing filter; sanitize its resulting event, not the earlier input.
The bounded sanitizer removes sensitive metadata, user fields other than opaque ID, request bodies/headers, URL query/fragment data and frame locals/source context while preserving diagnostic identity and trace/stack positions. It is not universal secret detection: application-specific sensitive values still need host policy. Logs, transactions, replay, profiles and attachments require separate configuration. Keep one application-owned SDK and capture lifecycle.
Testing
@playstack/errors/testing exports capture and no-op drivers plus a driver contract suite. Assert against normalized events without sending telemetry.
Boundary
The package does not own logging, tracing or span creation, breadcrumbs, alerting, storage, replay, profiling, SDK initialization, or automatic instrumentation. Use @playstack/errors-react and @playstack/nest-errors only at their respective framework edges.
API entry points and requirements
Reference snapshot: @playstack/errors@0.1.0-beta.1. Import only the entry point your runtime needs. Paths below are relative to the installed package; use Go to Definition in your editor to inspect exact parameters, return types and overloads. Do not import the declaration-file paths directly.
| Public entry point | Declaration file |
|---|---|
@playstack/errors | ./dist/index.d.ts |
@playstack/errors/errors | ./dist/errors.d.ts |
@playstack/errors/types | ./dist/types.d.ts |
@playstack/errors/validation | ./dist/validation.d.ts |
@playstack/errors/testing | ./dist/testing.d.ts |
@playstack/errors/sentry | ./dist/sentry.d.ts |
@playstack/errors/basemarks | ./dist/basemarks.d.ts |
@playstack/errors/playstack.integration.json | No TypeScript declaration (asset or metadata export). |
@playstack/errors/package.json | No TypeScript declaration (asset or metadata export). |
Node.js engine requirement: >=20. This is not a claim that every entry point works in browsers or Workers.
Peer dependencies
This package declares no peer dependencies. Its ordinary dependencies are resolved by the package manager.
For a complete first program, start with Getting started. For API lookup and partial-example conventions, see Reading the reference. Provider failures, lifecycle requirements and application responsibilities remain described in the guide above; types alone do not establish production safety.