@mushi-mushi/node
Server-side SDK for Node.js apps — forward unhandled exceptions, attach HTTP error-handler middleware to Express / Fastify / Hono, and tag every report with the route, request id, and user (when supplied).
Install
pnpm add @mushi-mushi/nodeExpress
import express from 'express'
import { mushiExpressErrorHandler } from '@mushi-mushi/node/express'
const app = express()
// …all your routes…
app.use(
mushiExpressErrorHandler({
apiKey: process.env.MUSHI_API_KEY!,
projectId: process.env.MUSHI_PROJECT_ID!,
environment: process.env.NODE_ENV,
release: process.env.GIT_SHA,
}),
) // mount LAST so it sees every other routeFastify
import Fastify from 'fastify'
import { mushiFastifyPlugin } from '@mushi-mushi/node/fastify'
const app = Fastify()
mushiFastifyPlugin(app, {
apiKey: process.env.MUSHI_API_KEY!,
projectId: process.env.MUSHI_PROJECT_ID!,
})Hono
import { Hono } from 'hono'
import { mushiHonoErrorHandler } from '@mushi-mushi/node/hono'
const app = new Hono()
app.onError(
mushiHonoErrorHandler({
apiKey: process.env.MUSHI_API_KEY!,
projectId: process.env.MUSHI_PROJECT_ID!,
}),
)Process-level fallbacks
Attach uncaughtException + unhandledRejection hooks so nothing escapes:
import { attachUnhandledHook } from '@mushi-mushi/node'
attachUnhandledHook({
apiKey: process.env.MUSHI_API_KEY!,
projectId: process.env.MUSHI_PROJECT_ID!,
})Programmatic submit
Use the client directly when you want to report outside the request cycle (cron jobs, queue workers, integration failures):
import { MushiNodeClient } from '@mushi-mushi/node'
const mushi = new MushiNodeClient({
apiKey: process.env.MUSHI_API_KEY!,
projectId: process.env.MUSHI_PROJECT_ID!,
environment: 'production',
release: process.env.GIT_SHA,
})
await mushi.captureReport({
description: 'Refund webhook returned 500',
severity: 'high',
component: 'billing',
metadata: { invoiceId, attempt },
})The Node SDK speaks the same wire protocol as the web SDK and shares classification quotas — server-thrown bugs and user-side bugs land in the same queue.
PII and credential scrubbing
Every description, url, and error.message value is passed through the
core PII scrubber before it leaves the process:
- JWT-shaped tokens (three dot-separated
eyJ…segments, regardless of header scheme) are redacted to[REDACTED_JWT]. - Emails, phone numbers and similar patterns are replaced with
[REDACTED_EMAIL],[REDACTED_PHONE], and friends. - Sensitive query-string keys (
token,api_key,password,secret, …) have their values replaced with[Scrubbed].
This applies to captureReport, mushiExpressErrorHandler, and
mushiTraceMiddleware — no extra configuration required.
If you use Authorization: Token <jwt> (Conduit / RealWorld spec), the JWT in
that header is never captured — the SDK only reads response status codes and
timing from network spans, not request headers.
The following fields are scrubbed before the report leaves the Node process:
| Field | Scrubber applied |
|---|---|
description | PII scrub (emails, phones, JWTs, SSNs, CC-shaped strings) |
environment.url | URL scrub (sensitive query-param keys and value patterns) |
error.message | PII scrub |
error.stack | PII scrub |
request.url (trace middleware) | URL scrub |
userId and host-supplied metadata are left unmodified — the SDK cannot know
which IDs or metadata keys are safe to alter, so the host is responsible for any
additional scrubbing at those sites.