Is there an existing issue for this?
How do you use Sentry?
Sentry Saas (sentry.io)
Which SDK are you using?
@sentry/nextjs
SDK Version
10.68.0
Framework Version
Next.js 16.2.11, @opennextjs/cloudflare 1.20.2, node 26.2.0, workerd compatibility_date 2026-04-14
Link to Sentry event
Private project — full stack and tags reproduced below.
Reproduction Example/SDK Setup
A Next.js app deployed to Cloudflare Workers via OpenNext, with the standard
instrumentation.ts setup:
// src/instrumentation.ts
import * as Sentry from "@sentry/nextjs";
export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
await import("../sentry.server.config");
}
}
Steps to Reproduce
import * as Sentry from "@sentry/nextjs" from any server module (instrumentation.ts, sentry.server.config.ts, a route handler).
- Build for Cloudflare Workers (
opennextjs-cloudflare build) and deploy.
- Trigger a cold start — any request will do.
Expected Result
The runtime bundle contains only runtime code. Nothing attempts
WebAssembly.compile() at module-evaluation time, since Cloudflare Workers
forbids runtime WASM compilation.
Actual Result
Every cold start raises an unhandled promise rejection:
CompileError: WebAssembly.compile(): Wasm code generation disallowed by embedder
at Context.commonJsRequire
at getOrInstantiateModuleFromParent
at instantiateModule
at module evaluation
Tagged unhandledPromiseRejection: true, with no route frames — the stack is
module evaluation only. In our project this produced 50 events over four days,
one per cold start, attributed to whichever request happened to warm the
isolate (44 of 50 have an empty transaction tag).
Root cause
@sentry/nextjs's server runtime entry re-exports the build-time config
helper, and that export's module graph reaches a bundler plugin containing an
inlined WASM module:
node_modules/@sentry/nextjs/build/esm/index.server.js:1
export { withSentryConfig } from './config/withSentryConfig/index.js';
-> config/withSentryConfig/buildTime.js:4,6
import { getTracingHooksDirectory } from '@sentry/server-utils/orchestrion/webpack';
import { sentryOrchestrionWebpackPlugin } from '@sentry/server-utils/orchestrion/webpack';
-> @sentry/server-utils/build/esm/orchestrion/bundler/webpack.js
-> @apm-js-collab/code-transformer-bundler-plugins@0.7.1
The plugin compiles an inlined base64 WASM module (a CJS/ESM lexer) at module**
**scope, unawaited:
g = WebAssembly.compile(d()).then(WebAssembly.instantiate).then(({exports: e}) => { u = e })
On Node that promise resolves and nobody notices. On Workers WebAssembly.compile
throws, and because the promise is never awaited it surfaces as an unhandled
rejection during module evaluation — with a stack that names no application code,
which makes it quite hard to attribute.
@sentry/cloudflare is not the culprit: build/esm/sdk.js:33-39 explicitly reads
channel integrations off a global marker rather than importing them, with a comment
saying this is "so bundles built without the plugin don't ship the code." That part
works as designed. The leak is the Next.js server entry.
What I verified
- The only dependency path to the plugin is
@sentry/cloudflare -> @sentry/server-utils -> @apm-js-collab/code-transformer-bundler-plugins@0.7.1, but the inclusion comes from the import chain above.
.next/server contains the plugin in 12 chunks, including the base64 WASM blob.
- Control build: removing
withSentryConfig from next.config.ts entirely and rebuilding leaves all 12 chunks unchanged. The build-time config file is not what pulls it in — importing @sentry/nextjs from a server module is.
@sentry/server-utils' main entry does not reach the plugin (it is confined to the ./orchestrion/* subpath exports), and the ./orchestrion barrel re-exports only channel integrations. So the subpath import in buildTime.js is the single crossing point.
Why this may matter beyond Workers
#22632 states the design assumption directly: "orchestrion only ships via
@sentry/node/{vite,webpack,rollup,esbuild} and framework server builds." That
assumption doesn't hold here — withSentryConfig sitting on index.server.js
puts the webpack plugin one import * as Sentry from "@sentry/nextjs" away from
any server bundle. Cloudflare Workers just makes it loud, because runtime WASM
compilation is a hard error there. Elsewhere it is silent bundle weight.
Suggested fix
Move withSentryConfig off the runtime server entry, or make
config/withSentryConfig/buildTime.js import the bundler plugin lazily
(await import(...) inside the function that uses it) so the WASM module isn't
reachable from module-evaluation of the runtime entry.
Workaround for others hitting this
Alias @sentry/server-utils/orchestrion/* to an empty module in the Worker build,
or import the runtime pieces from @sentry/cloudflare instead of @sentry/nextjs
where possible.
Is there an existing issue for this?
How do you use Sentry?
Sentry Saas (sentry.io)
Which SDK are you using?
@sentry/nextjs
SDK Version
10.68.0
Framework Version
Next.js 16.2.11, @opennextjs/cloudflare 1.20.2, node 26.2.0, workerd compatibility_date 2026-04-14
Link to Sentry event
Private project — full stack and tags reproduced below.
Reproduction Example/SDK Setup
A Next.js app deployed to Cloudflare Workers via OpenNext, with the standard
instrumentation.tssetup:Steps to Reproduce
import * as Sentry from "@sentry/nextjs"from any server module (instrumentation.ts,sentry.server.config.ts, a route handler).opennextjs-cloudflare build) and deploy.Expected Result
The runtime bundle contains only runtime code. Nothing attempts
WebAssembly.compile()at module-evaluation time, since Cloudflare Workersforbids runtime WASM compilation.
Actual Result
Every cold start raises an unhandled promise rejection:
Tagged
unhandledPromiseRejection: true, with no route frames — the stack ismodule evaluation only. In our project this produced 50 events over four days,
one per cold start, attributed to whichever request happened to warm the
isolate (44 of 50 have an empty
transactiontag).Root cause
@sentry/nextjs's server runtime entry re-exports the build-time confighelper, and that export's module graph reaches a bundler plugin containing an
inlined WASM module:
The plugin compiles an inlined base64 WASM module (a CJS/ESM lexer) at module**
**scope, unawaited:
On Node that promise resolves and nobody notices. On Workers
WebAssembly.compilethrows, and because the promise is never awaited it surfaces as an unhandled
rejection during module evaluation — with a stack that names no application code,
which makes it quite hard to attribute.
@sentry/cloudflareis not the culprit:build/esm/sdk.js:33-39explicitly readschannel integrations off a global marker rather than importing them, with a comment
saying this is "so bundles built without the plugin don't ship the code." That part
works as designed. The leak is the Next.js server entry.
What I verified
@sentry/cloudflare -> @sentry/server-utils -> @apm-js-collab/code-transformer-bundler-plugins@0.7.1, but the inclusion comes from the import chain above..next/servercontains the plugin in 12 chunks, including the base64 WASM blob.withSentryConfigfromnext.config.tsentirely and rebuilding leaves all 12 chunks unchanged. The build-time config file is not what pulls it in — importing@sentry/nextjsfrom a server module is.@sentry/server-utils' main entry does not reach the plugin (it is confined to the./orchestrion/*subpath exports), and the./orchestrionbarrel re-exports only channel integrations. So the subpath import inbuildTime.jsis the single crossing point.Why this may matter beyond Workers
#22632 states the design assumption directly: "orchestrion only ships via
@sentry/node/{vite,webpack,rollup,esbuild}and framework server builds." Thatassumption doesn't hold here —
withSentryConfigsitting onindex.server.jsputs the webpack plugin one
import * as Sentry from "@sentry/nextjs"away fromany server bundle. Cloudflare Workers just makes it loud, because runtime WASM
compilation is a hard error there. Elsewhere it is silent bundle weight.
Suggested fix
Move
withSentryConfigoff the runtime server entry, or makeconfig/withSentryConfig/buildTime.jsimport the bundler plugin lazily(
await import(...)inside the function that uses it) so the WASM module isn'treachable from module-evaluation of the runtime entry.
Workaround for others hitting this
Alias
@sentry/server-utils/orchestrion/*to an empty module in the Worker build,or import the runtime pieces from
@sentry/cloudflareinstead of@sentry/nextjswhere possible.