Skip to content

feat(cli): symbolicate Sentry crash traces via runtime sourcemaps#626

Closed
NisargIO wants to merge 1 commit into
mainfrom
worktree-snuggly-coalescing-bunny
Closed

feat(cli): symbolicate Sentry crash traces via runtime sourcemaps#626
NisargIO wants to merge 1 commit into
mainfrom
worktree-snuggly-coalescing-bunny

Conversation

@NisargIO
Copy link
Copy Markdown
Member

@NisargIO NisargIO commented Jun 1, 2026

cc @rayhanadev

What

Crash reports added in #621 currently land in Sentry with frames pointing at the bundled dist/cli.js (offsets like cli.js:1:48572), which aren't triage-able. This wires up on-device sourcemap symbolication so traces resolve to original-TypeScript positions (src/cli/...ts:line:col).

How

File Change
vite.config.ts sourcemap: true on the CLI pack entry only → emits dist/cli.js.map + a sourceMappingURL comment. The API entry stays map-free (it never initializes Sentry).
package.json Added dist/**/*.js.map to files so the map ships in the npm tarball.
bin/react-doctor.js process.setSourceMapsEnabled(true) before the import, so Node rewrites Error.stack to original positions before @sentry/node reads it.
.changeset/cli-sourcemaps.md patch bump.

Why the bin shim, and why before the import

setSourceMapsEnabled is a process-global switch, and Node caches a module's sourcemap at compile time — so it must be flipped on before dist/cli.js is compiled by the import(). Putting it inside the bundled TS would be too late for the bundle's own frames. Verified empirically (enable-before → frame maps to source; enable-after → frame stays on the bundled file). The call is guarded like enableCompileCache so an exotic/old runtime can't crash the CLI for the sake of an observability nicety.

Tradeoffs

  • External, not inline — keeps dist/cli.js lean; Node reads the map lazily, only when a stack is materialized (i.e. on a crash), so the no-crash path has zero added startup cost.
  • No upload step — symbolication is on-device; nothing is sent to Sentry's artifact store. (Debug-IDs + release upload remain a future option if we want server-side symbolication with context lines.)
  • No context lines — frames show file/line/function but no code snippet, since the original .ts files aren't shipped. Frame paths will include the user's local install path, consistent with the existing sendDefaultPii: true posture.

Testing

⚠️ Not built locally — this was authored in a worktree without installed deps. CI will build it; worth confirming pnpm build emits dist/cli.js.map + the sourceMappingURL comment, then triggering a deliberate throw to eyeball a symbolicated Sentry event before relying on it.

🤖 Generated with Claude Code

Emit an external sourcemap for the CLI bundle and turn on Node's
source-map support in the bin shim, so uncaught errors captured by
Sentry resolve to original-TypeScript positions instead of bundled
dist/cli.js offsets.

- vite.config.ts: `sourcemap: true` on the CLI pack entry only — the
  API entry stays map-free; it never initializes Sentry.
- package.json: ship `dist/**/*.js.map` in the published tarball.
- bin/react-doctor.js: `process.setSourceMapsEnabled(true)` before the
  `dist/cli.js` import. It must precede compile — Node caches a module's
  sourcemap at compile time, so enabling it from inside the already-loaded
  bundle is too late for the bundle's own frames. Guarded like
  `enableCompileCache` so a runtime without the API can't crash the CLI.

The map is external (not inlined) and read lazily by Node only when a
stack is materialized, so the no-crash path has no startup cost.
Symbolication happens on-device; no upload step.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@NisargIO NisargIO requested a review from rayhanadev June 1, 2026 09:20
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jun 1, 2026

Open in StackBlitz

npm i https://pkg.pr.new/eslint-plugin-react-doctor@626
npm i https://pkg.pr.new/oxlint-plugin-react-doctor@626
npm i https://pkg.pr.new/react-doctor@626

commit: 66eeddd

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

React Doctor

React Doctor found 4 files changed in this pull request, but none matched the files covered by its enabled checks.

Scope: 4 files changed on worktree-snuggly-coalescing-bunny vs. main.

View workflow run

Generated by React Doctor. Questions? Contact founders@million.dev.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant