Skip to content

@sentry/vite-plugin silently breaks event capture when combined with tauri-plugin-sentry #916

@ottosson

Description

@ottosson

I'm having problems using @sentry/vite-plugin with Tauri as it breaks the error logging. I've narrowed it to be the source maps generation. If I disable it the errors shows up in Sentry, if I enable it again the errors does not... I have a minimal reproducible example here: https://github.com/ottosson/sentry-vite-plugin-repro.

I've used Claude to find the problem and generate an issue (slop warning):


Summary

In a Tauri 2 app that uses tauri-plugin-sentry (which injects @sentry/browser into the webview and routes envelopes through a Tauri IPC transport to the Rust SDK), activating @sentry/vite-plugin at build time silently prevents most runtime errors from reaching Sentry. Manual Sentry.captureException(new Error(...)) still works, but errors thrown inside React event handlers, setTimeout callbacks, or any code path wrapped by browserApiErrorsIntegration are dropped. The SDK returns a looking-fine event ID; no envelope is ever produced.

The failure is narrowed to the plugin's per-chunk debug-ID injection:

  • Plugin skipped (SENTRY_AUTH_TOKEN unset at build) → every capture arrives.
  • Plugin active with sourcemaps.disable: true → every capture arrives.
  • Plugin active with default config → only manual captures arrive.

Minimal reproducer

https://github.com/ottosson/sentry-vite-plugin-repro (please fork/upload from the attached repro folder)

Three-button Tauri 2 app; each button exercises a different capture path. README walks through the three build variants.

Steps:

  1. npm install
  2. Replace DSN in src-tauri/src/lib.rs and org/project in vite.config.ts.
  3. Build with plugin active:
    $env:SENTRY_AUTH_TOKEN = "sntrys_..."
    npm run tauri build
  4. Install, click all three buttons.
  5. Observe in Sentry: only button 3 (manual capture) lands. Buttons 1 and 2 show Uncaught Error: ... in devtools console but produce no Sentry events.
  6. Rebuild with SENTRY_AUTH_TOKEN unset, or with sourcemaps: { disable: true } in the plugin config → all three buttons now produce events.

Environment

  • @sentry/vite-plugin 5.2.0 (also reproduces on 5.1.1)
  • @sentry/browser 10.46.0 (transitively via tauri-plugin-sentry)
  • tauri-plugin-sentry latest on main (timfish/sentry-tauri)
  • Tauri 2.10.x, React 19.2.x, react-dom 19.2.x
  • Vite 8.0.x, @vitejs/plugin-react 6.0.x
  • Windows 11, WebView2 Evergreen
  • Node 20+

Diagnostic observations

Hooking window.__TAURI_INTERNALS__.invoke to observe plugin:sentry|envelope calls:

  • Path A (plugin active): Sentry.captureException(err) invocations for React-onClick errors return an event ID but no envelope is invoked at the IPC level.
  • Path B (plugin absent): same code path produces an envelope.

Other observations that partially isolate the issue:

  • The thrown error has __sentry_captured__ === true after Sentry's browserApiErrorsIntegration wrapper runs. Explicitly stripping this marker does not restore delivery.
  • dedupeIntegration removal via integrations: (d) => d.filter((i) => i.name !== "Dedupe") does not restore delivery on its own.
  • setTimeout(() => Sentry.captureException(err), 0) deferral does not restore delivery.
  • Manual capture with a completely fresh new Error() (unique message + fresh stack) does land — which is why we suspect dedupe or marker-based gating at first, but those turn out not to be the individual cause.
  • Only avoiding the plugin's chunk-level debug-ID injection (either via sourcemaps.disable: true on the plugin, or by skipping the plugin entirely) restores delivery.

The injected snippet the plugin prepends to each chunk:

try {
  globalThis._sentryDebugIds = globalThis._sentryDebugIds || {};
  globalThis._sentryDebugIds[new Error().stack] = "<uuid>";
} catch {}

Something about this snippet — its timing, or the Error creation/stack capture, or the globalThis mutation — interacts with @sentry/browser v10's browserApiErrorsIntegration + dedupeIntegration in a way that causes the wrapper's own internal capture (and any subsequent application capture of the same error) to be silently dropped. I have not been able to pin it to a single integration.

What we need

Either:

  1. Confirmation that this combination (plugin + tauri-plugin-sentry's custom transport) is not a supported configuration, along with guidance on what to configure differently — or
  2. A fix in either the plugin's injection strategy or @sentry/browser's capture gating so that events produced during or after the wrapper's catch aren't silently discarded.

Metadata

Metadata

Assignees

Labels

BugSomething isn't working
No fields configured for issues without a type.

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions