# An error-tracking SDK is installed and actually initialized in code, with server-side coverage

- **Pattern:** `ab-002634` (`soc2-readiness.vuln-management-and-monitoring.error-tracking-initialized`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-07-03
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002634
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002634)

## Why it matters

SOC 2 CC7.2 requires that you monitor system components for anomalies, and the first question an auditor asks is "how do you know when production breaks?" An error-tracking service (Sentry, Bugsnag, Rollbar, Honeybadger) that aggregates exceptions and alerts a human is the standard code-level answer; `console.error` scrolling past in a log nobody tails is not. AI-generated apps fail this in a specific, repeatable way: the model adds `@sentry/nextjs` to package.json because the prompt mentioned "production ready", then never runs the wizard, so there is no `sentry.server.config.ts`, no `instrumentation.ts` register, and no DSN wiring. The dependency line looks like monitoring; unhandled server exceptions still vanish silently. Client-only inits are the second failure mode: browser errors get captured while the API routes that actually corrupt data report nothing. This check verifies the wiring in the repo (an init call with a DSN sourced from env, on the server side), which is exactly the code evidence a SOC 2 auditor will trace when testing CC7.2.

## Severity rationale

High because unwired error tracking means server-side failures in production go undetected until users report them, which is a direct CC7.2 monitoring gap an auditor will test on day one, though it does not by itself expose data.

## Remediation

Run `npx @sentry/wizard@latest -i nextjs` (or install `@sentry/node` for Express) and commit the generated config: `sentry.server.config.ts` plus an `instrumentation.ts` whose `register()` imports it, with `Sentry.init({ dsn: process.env.SENTRY_DSN })` reading the DSN from an environment variable, never a hardcoded string. For Express, call `Sentry.init` at the top of your server entry (`src/server.ts`) and add `Sentry.setupExpressErrorHandler(app)` so unhandled route exceptions are captured. Verify the init file is actually imported by the app entry path, not just sitting in the repo. Structured logging (pino, winston) is complementary but is not a substitute: the `saas-logging` audit covers that layer.

## Detection

- **ID:** `error-tracking-initialized`
- **Severity:** `high`
- **What to look for:** First determine whether this is a deployable app: a web/server framework in `package.json` (`next`, `express`, `fastify`, `koa`, `hono`, `remix`, `@sveltejs/kit`, `nuxt`), or `requirements.txt`/`pyproject.toml` with `django`/`flask`/`fastapi`, or a Go `main` package serving HTTP. If it is a library, CLI, or static-only site with no server code, skip. Otherwise enumerate: (a) an error-TRACKING dependency in `package.json`: `@sentry/nextjs`, `@sentry/node`, `@sentry/remix`, `@sentry/sveltekit`, `@bugsnag/js`, `@bugsnag/node`, `rollbar`, `@honeybadger-io/js`, `@highlight-run/node`, `@highlight-run/next` (Python: `sentry-sdk`, `bugsnag`, `rollbar`; Go: `github.com/getsentry/sentry-go`); and (b) a real init call in code: `Sentry.init(` in `sentry.server.config.{ts,js}`, `sentry.edge.config.{ts,js}`, or `instrumentation.{ts,js}` with a `register()` that imports the server config, or `Sentry.init(` / `Bugsnag.start(` / `new Rollbar(` / `Honeybadger.configure(` in a server entry (`src/server.ts`, `src/index.ts`, `app.ts`, `main.py`, `main.go`) with the DSN/API key read from env (`process.env.*`, `os.environ`, `os.Getenv`); and (c) server-side coverage: the init must exist in a server-executed file, not only `sentry.client.config.ts` or a `'use client'` component. Quote the actual dependency line and init call as you find them. Distinguish error tracking (an aggregation and alerting service) from error logging: `console.error`, `pino`, `winston`, or `morgan` alone never satisfy this check.
- **Pass criteria:** Deployable app, tracking dependency present, AND an uncommented server-side init call whose DSN/API key comes from an environment variable, AND that init file is reachable from the app (Next.js convention files `sentry.server.config.*`/`instrumentation.*` count as reachable by convention; for Express-style apps the init must be imported or called in the actual server entry). Before marking pass, quote the init call and its file path; a pass without a quoted server-side init excerpt is invalid. Do NOT pass merely because the dependency name appears in `package.json`, in a lockfile, or in a README: vocabulary presence is not wiring.
- **Fail criteria:** Deployable app with no error-tracking dependency at all; OR dependency installed but no init call anywhere (the classic half-wired AI-slop state: package.json line only); OR init exists but is commented out, gated behind an always-false condition, or lives in a file nothing imports; OR init is client-only (`sentry.client.config.ts` or browser `Bugsnag.start` with no server config or instrumentation register); OR the "init" is a stub with an empty or placeholder DSN string (`dsn: ''`, `dsn: 'YOUR_DSN_HERE'`).
- **Skip (N/A) when:** Not a deployable app (library, CLI tool, or static site with no server runtime). Quote: `"No server framework in package.json and no server entry point: not a deployable app, error tracking N/A"`.
- **Before evaluating, quote:** The dependency line from `package.json` (or its absence stated explicitly), plus the file path and a 1-3 line excerpt of the init call showing the DSN source. On the client-only fail variant, quote the client config path and state that no server config or instrumentation register was found.
- **Report even on pass:** `"Error tracking: <sdk> init at <path>, DSN from <env var>, server-side: yes"`.
- **Detail on fail:** `"@sentry/nextjs in package.json but no sentry.server.config.ts, no instrumentation.ts register, and no Sentry.init call anywhere: dependency installed, never wired"` or `"Sentry.init present only in sentry.client.config.ts; server routes under app/api/ have no error tracking: client-only coverage"`.
- **Remediation:** Run `npx @sentry/wizard@latest -i nextjs` and commit `sentry.server.config.ts` + `instrumentation.ts` with `Sentry.init({ dsn: process.env.SENTRY_DSN })`; for Express, init at the top of `src/server.ts` and add `Sentry.setupExpressErrorHandler(app)`. Logging pipelines (pino/winston) are covered separately by the `saas-logging` audit and do not substitute for tracking.

## External references

- soc2 CC7.2
- iso-27001 A.8.16
- nist SI-4

Taxons: observability, operational-readiness

HTML version: https://auditbuffet.com/patterns/ab-002634
