Skip to content

bug: Sentry esbuild plugin fails to upload sourcemaps #2865

@isshaddad

Description

@isshaddad

Provide environment information

N/A

Describe the bug

Expected behavior: Sourcemaps should be automatically uploaded to Sentry during deployment when using the sentryEsbuildPlugin with the documented configuration.

Actual behavior: No sourcemaps are uploaded. The plugin appears to run but doesn't detect or upload any files.

Potential root causes:

  1. Timing issue: The plugin runs during esbuild, but files aren't finalized yet. Even with placement: "last", the build continues modifying files, so the plugin can't find them.

  2. File extension mismatch: Trigger.dev outputs .mjs and .mjs.map files, but Sentry's plugin defaults to looking for .js and .js.map files.

  3. Path prefix mismatch: Sentry expects paths prefixed with /app/, but the built sourcemap files don't have this prefix.

Reproduction repo

N/A

To reproduce

  1. Configure sentryEsbuildPlugin in trigger.config.ts as documented:
import { defineConfig } from "@trigger.dev/sdk";
import { esbuildPlugin } from "@trigger.dev/build/extensions";
import { sentryEsbuildPlugin } from "@sentry/esbuild-plugin";

export default defineConfig({
  project: "<project ref>",
  build: {
    extensions: [
      esbuildPlugin(
        sentryEsbuildPlugin({
          org: process.env.SENTRY_ORG,
          project: process.env.SENTRY_PROJECT,
          authToken: process.env.SENTRY_AUTH_TOKEN,
        }),
        { placement: "last", target: "deploy" }
      ),
    ],
  },
});
  1. Set required environment variables (SENTRY_ORG, SENTRY_PROJECT, SENTRY_AUTH_TOKEN, COMMIT)

  2. Run trigger.dev deploy

  3. Check Sentry dashboard - no sourcemaps are uploaded

Additional information

Workaround solution

Workaround implemented using the onBuildComplete hook:

{
  name: "sentry-sourcemap-upload",
  async onBuildComplete(context, manifest) {
    if (context.target !== "deploy") {
      context.logger.debug(
        "[Sentry] Skipping sourcemap upload for non-deploy target",
      );
      return;
    }

    const release = process.env.COMMIT;
    const authToken = process.env.SENTRY_AUTH_TOKEN;

    if (!release || !authToken) {
      context.logger.warn(
        "[Sentry] Missing required env vars, skipping sourcemap upload",
      );
      return;
    }

    const outputPath = manifest.outputPath;
    context.logger.log(
      `[Sentry] Uploading sourcemaps from ${outputPath} for release ${release}`,
    );

    const { execSync } = await import("child_process");
    try {
      // Create the release
      execSync(
        `npx @sentry/cli releases new ${release} --org replo-hq --project trigger`,
        {
          env: { ...process.env, SENTRY_AUTH_TOKEN: authToken },
          stdio: "inherit",
        },
      );

      // Inject debug IDs into the built files. This modifies the .mjs files
      // to include debug IDs that Sentry uses to match errors to sourcemaps.
      execSync(
        `npx @sentry/cli sourcemaps inject --ext mjs --ignore node_modules "${outputPath}"`,
        {
          env: { ...process.env, SENTRY_AUTH_TOKEN: authToken },
          stdio: "inherit",
        },
      );

      // Upload sourcemaps (debug IDs are now in both .mjs and .mjs.map files)
      execSync(
        `npx @sentry/cli sourcemaps upload --release ${release} --org replo-hq --project trigger --ext mjs --ext map --ignore node_modules --url-prefix /app/ "${outputPath}"`,
        {
          env: { ...process.env, SENTRY_AUTH_TOKEN: authToken },
          stdio: "inherit",
        },
      );

      // Finalize the release
      execSync(
        `npx @sentry/cli releases finalize ${release} --org replo-hq --project trigger`,
        {
          env: { ...process.env, SENTRY_AUTH_TOKEN: authToken },
          stdio: "inherit",
        },
      );

      context.logger.log("[Sentry] Sourcemap upload complete");
    } catch (error) {
      context.logger.warn(`[Sentry] Sourcemap upload failed: ${error}`);
    }
  },
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions