Skip to content

Sourcemap not working with esbuild #803

@gsabran

Description

@gsabran

Environment

@sentry/esbuild-plugin@^4.3.0
node --version
v22.13.1
macOS 15.5 (24F74)

Steps to Reproduce

I've been following the documentation to upload sourcemaps. However the logs don't show code mapping:

Image
tsconfig.json
{
	"compilerOptions": {
		"target": "esnext",
		"module": "esnext",
		"moduleResolution": "bundler",
		"declaration": true,
		"strict": true,
		"noImplicitAny": false /* Raise error on expressions and declarations with an implied 'any' type. */,
		"strictNullChecks": true,
		"strictFunctionTypes": true /* Enable strict checking of function types. */,
		"noUnusedLocals": false /* Report errors on unused locals. */,
		"noUnusedParameters": false /* Report errors on unused parameters. */,
		"noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
		"noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
		"importHelpers": true,
		"skipLibCheck": true,
		"esModuleInterop": true,
		"allowSyntheticDefaultImports": true,
		"experimentalDecorators": true,
		"sourceMap": true,
		"inlineSources": true,
		"outDir": "./dist/tsc/",
		"types": ["node", "jest"],
		"lib": ["ES2024", "DOM"],
		"baseUrl": ".",
		"paths": {
			"@/*": ["src/*"]
		},
		"incremental": true,
		"tsBuildInfoFile": "./dist/tsc/.tsbuildinfo"
	},
	"include": ["src/**/*.ts", "tools/**/*.ts"],
	"exclude": ["node_modules", "dist", "coverage", "**/__snapshots__/**"]
}
build.js
import * as esbuild from "esbuild"
import esbuildPluginTsc from "esbuild-plugin-tsc"
import fs from "fs/promises"
import { sentryEsbuildPlugin } from "@sentry/esbuild-plugin"

const buildOptions = {
	entryPoints: ["src/main.ts"],
	outfile: "dist/main.bundle.cjs",
	bundle: true,
	plugins: [
		esbuildPluginTsc({
			tsconfigPath: "./tsconfig.json",
			force: true,
		}),
	],
	sourcemap: true,
	platform: "node",
	minify: true,
}

if (process.env.NODE_ENV === "production") {
	buildOptions.define = { "process.env.NODE_ENV": '"production"' }

	if (process.env.SENTRY_AUTH_TOKEN === undefined) {
		throw new Error("SENTRY_AUTH_TOKEN is not defined and required for production build")
	}
	buildOptions.plugins.push(sentryEsbuildPlugin({
		authToken: process.env.SENTRY_AUTH_TOKEN,
		org: "<org>",
		project: "<project>",
		telemetry: false,
		debug: true,
	}))
} else {
	buildOptions.define = { "process.env.NODE_ENV": '"development"' }
}

const plugins = [
	{
		name: "post-build-plugin",
		setup(build) {
			build.onEnd(async (result) => {
				if (process.env.NODE_ENV === "production") {
					// Remove the sourcemap, as it has been uploaded to Sentry.
					await fs.unlink("./dist/main.bundle.cjs.map")
				}
			})
		},
	},
]

export const ctx = await esbuild.context({ ...buildOptions, plugins: [...buildOptions.plugins, ...plugins] })

// Check if --watch flag is present in process arguments
if (process.argv.includes("--watch")) {
	// Set up watch mode with hash computation after each rebuild
	ctx.watch()
} else {
	ctx.rebuild()
	ctx.dispose()
}
$ SENTRY_AUTH_TOKEN=... NODE_ENV=production node ./build.js

[sentry-esbuild-plugin] Debug: No `sourcemaps.assets` option provided, falling back to uploading detected build artifacts.
[sentry-esbuild-plugin] Debug: Source map found for bundle `/Users/guigui/dev/cmd/local-server/dist/main.bundle.cjs`: `/Users/guigui/dev/cmd/local-server/dist/main.bundle.cjs.map`
> Found 2 files
> Analyzing 2 sources
> Analyzing completed in 0.017s
> Adding source map references
> Bundling completed in 0.25s
> Bundled 2 files for upload
> Bundle ID: ea74d12d-165f-5e6c-b906-b938c330d101
> Optimizing completed in 0.005s
> Uploading completed in 1.82s
> Uploaded files to Sentry
> Processing completed in 0.184s
> File upload complete (processing pending on server)
> Organization: <Organization>
> Projects: <Projects>
> Release: 96113a8a19990d0a6531580aa5d12ff87377221b
> Dist: None
> Upload type: artifact bundle

Source Map Upload Report
  Scripts
    ~/3e7bec8d-7bf5-456e-b486-cc12baa40a89-0.js (sourcemap at 3e7bec8d-7bf5-456e-b486-cc12baa40a89-0.js.map, debug id 3e7bec8d-7bf5-456e-b486-cc12baa40a89)
  Source Maps
    ~/3e7bec8d-7bf5-456e-b486-cc12baa40a89-0.js.map (debug id 3e7bec8d-7bf5-456e-b486-cc12baa40a89)
[sentry-esbuild-plugin] Info: Successfully uploaded source maps to Sentry
build completed in 6156ms (429bb814da4aa05a555f575ce5bdfe54302aa790ea99553a71086464d6fca3b0)

The debug id seems correctly inserted in the bundle. I assume that the uploaded artifacts have also been modified to contain it:

$ cat ./dist/main.bundle.cjs | grep -oE ".{0,10}3e7bec8d-7bf5-456e-b486-cc12baa40a89.{0,10}"
ugIds[e]="3e7bec8d-7bf5-456e-b486-cc12baa40a89",t._sentr
ntry-dbid-3e7bec8d-7bf5-456e-b486-cc12baa40a89")})()}cat

I then run node ./dist/main.bundle.cjs and trigger an error. The error is reported to Sentry, but the trace is not mapped back to the original code.

If useful, this is in an open source repo, in this branch: https://github.com/getcmd-dev/cmd/tree/gui--node-sentry/local-server

Expected Result

See the error in Sentry with a trace that maps to the original typescript code.

Actual Result

See screenshot. The error trace points to lines in the minified js bundle.

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    Waiting for: Community

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions