Skip to content

fix(browser): forward uncaught worker errors with their stack - #24210

Open
d2anamaria wants to merge 2 commits into
developfrom
ana/fix/wasm/worker-uncaught
Open

fix(browser): forward uncaught worker errors with their stack#24210
d2anamaria wants to merge 2 commits into
developfrom
ana/fix/wasm/worker-uncaught

Conversation

@d2anamaria

Copy link
Copy Markdown
Contributor

Uncaught errors thrown inside a web worker reach Sentry without a usable stack.
They bubble to the page, so an event is still created, but the propagated
ErrorEvent carries no error object — only a message string. The result is an
event with a single synthetic frame pointing at the worker bundle and a value
prefixed with Uncaught .

For plain JavaScript that degrades acceptably: one frame plus a sourcemap still
locates the throw. For WebAssembly it fails outright. No frame carries a wasm
URL, so the wasm integration finds nothing to match and the event ships with no
debug images, even though the worker's images already reached the page. An
uncaught wasm trap in a worker is unsymbolicatable today, while the identical
trap wrapped in try/catch symbolicates fine.

Root cause

registerWebWorker only forwarded unhandled rejections, on the assumption that
synchronous errors were already covered by the global handlers. They are
captured, but only from the message string, because an error that crosses a
worker boundary loses its error object by design.

Solution

Uncaught worker errors are now forwarded to the page over the same channel that
already carries rejections. Structured clone preserves message, stack and
cause, so the page receives a real error and parses a real stack — the same
outcome the caught path already produced. Wasm frames then match their debug
images and symbolicate normally. Forwarded errors are distinguishable from
rejections by their mechanism, and the worker's stack trace limit now matches
the page's so deep stacks are no longer truncated before being sent.

Limitations

The error still bubbles to the page after being forwarded, so a second,
frameless event is emitted for the same throw. Deduplication does not merge the
two, because one has a stack and the other does not. Cancelling the error inside
the worker would collapse them, but would also stop the browser printing its own
uncaught report in DevTools — a real debugging regression. This is left open
deliberately and is the main thing worth a second opinion.

Errors whose value cannot be structured-cloned are forwarded as a description
rather than the original value.

Workers registered by an older SDK version are still treated as rejection-only,
so mixed-version setups keep working.

- Add an `error` listener in `registerWebWorker` that posts `event.error`
  (falling back to `event.message`) over the existing `_sentryWorkerError` channel
- Add optional `kind` discriminator to `SerializedWorkerError`; a missing `kind`
  means rejection, so workers registered by an older SDK keep working
- Rename `handleForwardedWorkerRejection` to `handleForwardedWorkerError` and
  branch on `kind` for both the mechanism and `eventFromUnknownInput`'s
  `isUnhandledRejection` argument
- Report forwarded throws under the `auto.browser.web_worker.onerror` mechanism
- Restrict `_eventFromRejectionWithPrimitive` to rejections so a thrown primitive
  is not labelled "Non-Error promise rejection"
- Set `Error.stackTraceLimit = 50` in the worker, matching globalHandlersIntegration,
  since V8's default of 10 truncates stacks before they are forwarded
- Wrap the forwarding `postMessage` so a non-cloneable reason is described instead
  of raising DataCloneError out of the worker's error handler
- Correct the doc comment claiming globalHandlers already captures sync worker errors
@d2anamaria
d2anamaria requested a review from a team as a code owner September 8, 2026 14:45
@d2anamaria
d2anamaria requested review from andreiborza, logaretm and msonnb and removed request for a team September 8, 2026 14:45

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 725ad37. Configure here.

Comment thread packages/browser/src/integrations/webWorker.ts
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 28.8 kB added added
@sentry/browser - with treeshaking flags 27.11 kB added added
@sentry/browser - with treeshaking flags tracing without tracing 27 kB added added
@sentry/browser (incl. Tracing) 49.22 kB added added
@sentry/browser (incl. Tracing + Span Streaming) 49.22 kB added added
@sentry/browser (incl. Tracing, Profiling) 52.12 kB added added
@sentry/browser (incl. Tracing, Replay) 88.76 kB added added
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 77.95 kB added added
@sentry/browser (incl. Tracing, Replay with Canvas) 93.44 kB added added
@sentry/browser (incl. Tracing, Replay, Feedback) 106.37 kB added added
@sentry/browser (incl. Feedback) 46.3 kB added added
@sentry/browser (incl. sendFeedback) 33.86 kB added added
@sentry/browser (incl. FeedbackAsync) 38.97 kB added added
@sentry/browser (incl. Metrics) 29.82 kB added added
@sentry/browser (incl. Logs) 30.09 kB added added
@sentry/browser (incl. Metrics & Logs) 30.75 kB added added
@sentry/react 30.55 kB added added
@sentry/react (incl. Tracing) 51.56 kB added added
@sentry/vue 36.05 kB added added
@sentry/vue (incl. Tracing) 51.48 kB added added
@sentry/svelte 28.83 kB added added
CDN Bundle 30.55 kB added added
CDN Bundle (incl. Tracing) 49.74 kB added added
CDN Bundle (incl. Logs, Metrics) 32.82 kB added added
CDN Bundle (incl. Tracing, Logs, Metrics) 51.7 kB added added
CDN Bundle (incl. Replay, Logs, Metrics) 73.48 kB added added
CDN Bundle (incl. Tracing, Replay) 87.29 kB added added
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 89.18 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback) 93.22 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 95.21 kB added added
CDN Bundle - uncompressed 90.46 kB added added
CDN Bundle (incl. Tracing) - uncompressed 148.17 kB added added
CDN Bundle (incl. Logs, Metrics) - uncompressed 97.03 kB added added
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 154.14 kB added added
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 226.29 kB added added
CDN Bundle (incl. Tracing, Replay) - uncompressed 267.76 kB added added
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 273.71 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 281.46 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 287.4 kB added added
@sentry/nextjs (client) 54 kB added added
@sentry/sveltekit (client) 49.65 kB added added
@sentry/core/server 36.99 kB added added
@sentry/core/browser 13.55 kB added added
@sentry/node 127.86 kB added added
@sentry/node/import (ESM hook with diagnostics-channel injection) 81.61 kB added added
@sentry/node - without tracing 88.73 kB added added
@sentry/node - without channel injection 107.11 kB added added
@sentry/aws-serverless 97.12 kB added added
@sentry/cloudflare (withSentry) - minified 201.98 kB added added
@sentry/cloudflare (withSentry) 502.68 kB added added

View base workflow run

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