Source Map
Generate and upload source maps so production stack traces point at your original TypeScript.
Why
A prod stack trace that says 'at a (chunk-abc123.js:1:4587)' is useless — you can't debug minified, bundled code without translating it back to the source. Source maps are the translation layer: with them, Sentry shows 'at checkout (src/routes/checkout.ts:42:7)' and you fix the bug in 30 seconds; without them, you stare at a minified one-liner for an hour and give up. The catch is that source maps must NOT be publicly served (they leak your source code), so the workflow is: build generates them, CI uploads them to your error tracker, then deletes them from the deploy artifact. Skipping this is the single biggest reason 'prod bugs are impossible to debug'.
When
Before the first prod deploy. Takes 15-30 min to wire into CI. Skip only if you ship unminified code.
How
1. Enable source maps in the build config (devtool / sourcemap) - Vite: build.sourcemap = true - Next.js: productionBrowserSourceMaps: true (or experimental for server) - esbuild/tsc: --sourcemap flag 2. Choose hidden source maps (no // sourceMappingURL comment in the prod bundle) - The bundle stays clean; maps are uploaded separately to the error tracker - Vite: sourcemap: 'hidden'; Webpack: devtool: 'hidden-source-map' 3. Upload maps to your error tracker in CI, keyed by the release version - Sentry: sentry-cli sourcemaps upload --release <version> ./dist - The release tag must match what the app reports at runtime 4. Delete the .map files from the deploy artifact after upload - They should never be served publicly — they reverse-minify your code for anyone who downloads them - Add a CI step: rm -rf dist/**/*.map after the upload 5. Verify end-to-end: trigger a deliberate error in prod, confirm the trace shows the .ts file and line - If it still shows .js, the release tag mismatch or the map didn't upload
Example
// vite.config.ts — hidden source maps in prod
export default defineConfig({
build: {
sourcemap: process.env.NODE_ENV === "production" ? "hidden" : true,
},
});
# .github/workflows/release.yml — upload then delete
- run: pnpm build
- run: |
pnpm exec sentry-cli sourcemaps upload \
--release ${{ github.sha }} \
--dist-prefix ./dist ./dist
- run: Remove-Item -Recurse -Force dist/**/*.map # never ship maps publicly
- run: pnpm exec vercel deploy --prebuilt
// verify at runtime — the error tracker should show the .ts path
throw new Error("deliberate prod test"); // expect: src/routes/checkout.ts:42Common Problems
- ⚠Shipping .map files publicly alongside the bundle — anyone can reverse your minified app to full source.
- ⚠Forgetting to tag the upload with the release version, so Sentry can't match the error to the map.
- ⚠Enabling source maps only for the client, not the server — serverless function errors stay opaque.
- ⚠Uploading maps but not deleting them from the artifact, so the deploy is 2x larger than needed.
Best Practices
- ✓Use hidden source maps (no sourceMappingURL comment) so the browser never requests them but your error tracker can still find them by release tag.
- ✓Tag every release with the git SHA and pass the same SHA to both the upload and the runtime SDK — a mismatch is the #1 reason traces don't resolve.
- ✓For serverless, upload maps per-function (Sentry supports this) so each function's trace resolves independently.
- ✓Test the pipeline with a deliberate error on every release — if the trace doesn't resolve, fix it before the real bugs arrive.