Web Workers
Learn how to use Sentry's Browser SDK in Web Workers API.
Sentry's Browser SDK supports the Web Workers API. You can use the SDK in different ways, though we recommend initializing it in the main thread to capture unhandled errors from workers automatically.
Available since : 9.40.0
To capture unhandled errors from Web Workers, initialize Sentry in your application code that runs on the main thread and let the SDK know about the web worker:
index.js
import * as Sentry from "@sentry/browser";
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
});
const worker = new Worker("worker.js");
// Add the integration before listening to worker messages
Sentry.addIntegration(Sentry.webWorkerIntegration({ worker }));
worker.onmessage = (event) => {
// ...
};
Then, establish communication between the worker and the SDK:
worker.js
import * as Sentry from "@sentry/browser";
// Call this before posting any message
Sentry.registerWorker({ self });
// Errors from `onmessage` callback of `worker.js`
// will be captured automatically.
self.postMessage("Worker ready!");
self.onmessage = (event) => {
// ...
};
The Order Matters
Ensure that in both, your main thread code as well as the worker, you set up Sentry before you start listening to messages. The Sentry SDK sends messages from the worker to the main thread, so if you start listening before Sentry is initialized, the messages will appear in your listeners and you have to handle them manually.
The sentryWebWorkerIntegration
supports registering multiple workers. You can add them directly, when you initialize the integration, or later on. This is helpful, if you have workers that are initialized at different points in time in your application lifecycle.
index.js
import * as Sentry from "@sentry/browser";
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
});
const worker1 = new Worker("worker.js");
const worker2 = new Worker("worker2.js");
// Multiple workers can be added directly:
const webWorkerIntegration = Sentry.webWorkerIntegration({
worker: [worker1, worker2],
});
Sentry.addIntegration(webWorkerIntegration);
// or later on:
const worker3 = new Worker("worker3.js");
webWorkerIntegration.addWorker(worker3);
Keep in Mind
- Every worker must call
Sentry.registerWorker({ self })
to register itself with the SDK. - Do not call
Sentry.webWorkerIntegration()
multiple times! This will lead to unexpected behavior.
To capture errors or messages manually, via Sentry.captureMessage
or Sentry.captureException
inside Web Workers, you can also import the SDK in the worker and initialize it.
worker.js
import * as Sentry from "@sentry/browser";
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
});
self.onmessage = (message) => {
// This message will be captured
Sentry.captureMessage("Message received");
// This error will also be captured.
throw new Error();
};
Note that initializing the SDK in the worker completely decouples it from the SDK running on the main thread. This means that data like user, tags, traces or scope data set on either side will not be shared with the other side.
Sometimes, this is the better approach, for instance if you develop a worker that is used in arbitrary applications. Other times, if the worker is just part of your application, you likely want to use the SDK from the main thread.
Keep in Mind
If you initialize the SDK in the worker, don't use the Sentry.webWorkerIntegration
to register the worker. Likewise, don't use the Sentry.registerWorker
in the worker. Both methods are only supposed to be used when relying on the SDK from the main thread.
Note, that if you use non-default integrations inside web workers, they may not function as expected. However, non-default integrations that are enabled on the main thread SDK, won't be affected and will work as expected. This includes Session Replay.
To ensure that errors from web workers are properly mapped to their original source code, you need to provide source maps to Sentry. You likely already provide source maps to Sentry for your main application code, but you might need to make adjustments for your worker.
Importantly, ensure that your bundler also emits source maps for the worker bundle(s).
If you use Vite to build your worker, note that the worker build does not take the same plugin as the main code build. Therefore, you need to add Sentry's Vite plugin to the worker build, in addition to the top-level plugins
array:
vite.config.mjs
const sentryPlugin = sentryVitePlugin({
org: "sentry-sdks",
project: "javascript",
});
export default defineConfig({
build: {
// This enables source maps for main and worker bundles
sourcemap: "hidden",
},
// Vite plugin for main bundle
plugins: [sentryPlugin],
worker: {
// Vite plugin for worker bundle
plugins: () => [...sentryPlugin],
},
});
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").