Is there an existing issue for this?
How do you use Sentry?
Sentry SaaS (sentry.io)
Which SDK are you using?
@sentry/tanstackstart-react
SDK Version
10.46.0
Framework Version
TanStack Start ~1.166 (React 19, SSR via Nitro ~3.0)
Link to Sentry event
No response
Reproduction Example/SDK Setup
The core claim — that the workerd/worker conditions resolve to a file that re-exports @sentry/node — is verifiable directly from the package metadata and source without any app:
- Inspect
packages/tanstackstart-react/package.json — workerd, worker, and node all resolve to index.server.js
- Inspect
build/esm/index.server.js — does export * from '@sentry/node'
For the runtime failure:
- Create a TanStack Start app deployed to Cloudflare Workers (Nitro
cloudflare-module preset, noExternals: true)
- Install
@sentry/tanstackstart-react@10.46.0
- Import in
router.tsx (SSR entry): import * as Sentry from '@sentry/tanstackstart-react'
- Set
ssr.resolve.conditions: ['workerd', 'worker', 'browser', 'import', 'module', 'default'] in Vite config
- Build and deploy — the Worker returns HTTP 500 with
"Cannot initialize ExportedHandler"
Because Nitro uses noExternals: true for Workers (no node_modules at runtime), the package is not externalized. Vite resolves it using ssr.resolve.conditions (not ssr.resolve.externalConditions), so the workerd condition takes effect and routes to index.server.js.
Steps to Reproduce
@sentry/tanstackstart-react advertises workerd and worker export conditions in its package.json, suggesting compatibility with Cloudflare Workers and similar edge runtimes. However, all three server-side conditions (workerd, worker, node) resolve to the exact same file — index.server.js — which re-exports @sentry/node.
The Node-orientation is not limited to the barrel re-export. The server source modules themselves import directly from @sentry/node:
When bundled for Workers (where @sentry/tanstackstart-react is non-externalized and resolved under the workerd condition), this pulls the @sentry/node dependency tree — including @opentelemetry/instrumentation-undici and transitive node:* built-in imports — into the Worker bundle. While Cloudflare Workers with nodejs_compat do support many Node APIs to varying degrees, in our deployment this caused module evaluation failure: the Worker's default export became null, producing "Cannot initialize ExportedHandler" at runtime with no stack trace. The exact failure mechanism likely depends on which node:* shims are partial or missing for the given compatibility date, but the root issue is that Workers resolves to a Node SDK entry that was never designed for this runtime.
package.json exports (v10.46.0):
{
"exports": {
".": {
"workerd": {
"import": "./build/esm/index.server.js",
"require": "./build/cjs/index.server.js"
},
"worker": {
"import": "./build/esm/index.server.js",
"require": "./build/cjs/index.server.js"
},
"browser": {
"import": "./build/esm/index.client.js",
"require": "./build/cjs/index.client.js"
},
"node": {
"import": "./build/esm/index.server.js",
"require": "./build/cjs/index.server.js"
}
}
}
}
workerd, worker, and node all resolve to index.server.js. Only browser resolves to index.client.js. The same export map is present on the develop branch, so this is a current packaging issue.
Expected Result
The workerd and worker export conditions should not resolve to code that re-exports @sentry/node.
Minimal fix — remove misleading conditions:
Remove the workerd and worker export conditions from package.json, since the package does not currently provide Workers-compatible server code. This is a packaging stopgap, not a fully non-breaking resolution:
- Fallback behavior is toolchain-dependent. Bundlers whose active condition set includes
browser (e.g., Vite with ['workerd', 'worker', 'browser', ...]) will fall through to index.client.js, which is safe. But this is not guaranteed across all resolvers — Node's package docs recommend a default branch for unknown runtimes. Whether to add default pointing to the client entry is a design call for the Sentry team.
- Export surface change. The
browser/client entry exports stubs for wrapMiddlewaresWithSentry, sentryGlobalRequestMiddleware, and sentryGlobalFunctionMiddleware, but it does not export wrapFetchWithSentry. Consumers who import that helper would get a build error. The shared index.types.ts still re-exports the full server API surface, so TypeScript types and runtime exports would diverge for Workers consumers.
Despite these caveats, removing the conditions is strictly better than the current state: it stops actively directing Workers bundlers to Node code, and the practical impact is limited since the server helpers don't work on Workers anyway.
Longer-term — proper Workers entry (follow-up):
A proper fix would create Worker-specific server modules that use @sentry/cloudflare instead of @sentry/node. This is non-trivial since @sentry/node is imported directly by multiple server source files, not just the barrel. This would likely be a separate design effort, potentially tracked alongside JS-1388.
Actual Result
Worker crashes with "Cannot initialize ExportedHandler" — silent module evaluation failure, no stack trace, no useful output from wrangler tail.
| Condition resolved |
Server entry |
What gets bundled |
Result on Workers |
workerd |
index.server.js |
@sentry/node + OpenTelemetry + node:* |
Silent crash |
worker |
index.server.js |
@sentry/node + OpenTelemetry + node:* |
Silent crash |
browser |
index.client.js |
@sentry/browser (no Node deps) |
Works |
node |
index.server.js |
@sentry/node |
Works (Node.js) |
Workaround: Replace @sentry/tanstackstart-react with @sentry/react for runtime imports. Both export init, ErrorBoundary, and tanstackRouterBrowserTracingIntegration. This preserves client-side Sentry but loses the TanStack Start server helpers. For server-side Workers tracking, use @sentry/cloudflare separately. The Vite plugin (@sentry/tanstackstart-react/vite) is build-time only and unaffected.
Related issues
- JS-1388 — Investigate TanStack Start React Cloudflare support
- #12620 — Sentry Cloudflare Workers SDK
- JS-348 — Support Next.js on Cloudflare Workers (OpenNext) (same pattern with
@sentry/nextjs)
- JS-1481 — Cannot resolve
@sentry/nextjs on Cloudflare Workers (same class of bug)
- JS-377 — React Router v7 deployed to Cloudflare Workers
Additional context
Note: We are aware the SDK setup docs note this is still alpha and warn that the setup "does not currently work for Cloudflare deployments." This issue is specifically about the misleading workerd/worker export conditions — they signal bundler-level compatibility that doesn't exist, causing a silent failure mode that is very difficult to diagnose.
Environment details: Cloudflare Workers paid plan, compatibility date 2025-09-01, nodejs_compat enabled. Bundling via Vite 7 (Rolldown) with Nitro noExternals: true.
We observed platform-dependent behavior: macOS local builds sometimes tree-shook enough undici code for the Worker to boot, while Linux CI included the full transport (~900 KiB), causing module evaluation failure. This variance is secondary to the export-map mismatch but made diagnosis significantly harder.
Is there an existing issue for this?
How do you use Sentry?
Sentry SaaS (sentry.io)
Which SDK are you using?
@sentry/tanstackstart-reactSDK Version
10.46.0
Framework Version
TanStack Start ~1.166 (React 19, SSR via Nitro ~3.0)
Link to Sentry event
No response
Reproduction Example/SDK Setup
The core claim — that the
workerd/workerconditions resolve to a file that re-exports@sentry/node— is verifiable directly from the package metadata and source without any app:packages/tanstackstart-react/package.json—workerd,worker, andnodeall resolve toindex.server.jsbuild/esm/index.server.js— doesexport * from '@sentry/node'For the runtime failure:
cloudflare-modulepreset,noExternals: true)@sentry/tanstackstart-react@10.46.0router.tsx(SSR entry):import * as Sentry from '@sentry/tanstackstart-react'ssr.resolve.conditions: ['workerd', 'worker', 'browser', 'import', 'module', 'default']in Vite config"Cannot initialize ExportedHandler"Because Nitro uses
noExternals: truefor Workers (nonode_modulesat runtime), the package is not externalized. Vite resolves it usingssr.resolve.conditions(notssr.resolve.externalConditions), so theworkerdcondition takes effect and routes toindex.server.js.Steps to Reproduce
@sentry/tanstackstart-reactadvertisesworkerdandworkerexport conditions in itspackage.json, suggesting compatibility with Cloudflare Workers and similar edge runtimes. However, all three server-side conditions (workerd,worker,node) resolve to the exact same file —index.server.js— which re-exports@sentry/node.The Node-orientation is not limited to the barrel re-export. The server source modules themselves import directly from
@sentry/node:src/server/index.ts— re-exports from@sentry/nodesrc/server/sdk.ts— imports@sentry/nodeforinitsrc/server/wrapFetchWithSentry.ts— imports from@sentry/nodesrc/server/middleware.ts— imports from@sentry/nodeWhen bundled for Workers (where
@sentry/tanstackstart-reactis non-externalized and resolved under theworkerdcondition), this pulls the@sentry/nodedependency tree — including@opentelemetry/instrumentation-undiciand transitivenode:*built-in imports — into the Worker bundle. While Cloudflare Workers withnodejs_compatdo support many Node APIs to varying degrees, in our deployment this caused module evaluation failure: the Worker's default export becamenull, producing"Cannot initialize ExportedHandler"at runtime with no stack trace. The exact failure mechanism likely depends on whichnode:*shims are partial or missing for the given compatibility date, but the root issue is that Workers resolves to a Node SDK entry that was never designed for this runtime.package.jsonexports (v10.46.0):{ "exports": { ".": { "workerd": { "import": "./build/esm/index.server.js", "require": "./build/cjs/index.server.js" }, "worker": { "import": "./build/esm/index.server.js", "require": "./build/cjs/index.server.js" }, "browser": { "import": "./build/esm/index.client.js", "require": "./build/cjs/index.client.js" }, "node": { "import": "./build/esm/index.server.js", "require": "./build/cjs/index.server.js" } } } }workerd,worker, andnodeall resolve toindex.server.js. Onlybrowserresolves toindex.client.js. The same export map is present on thedevelopbranch, so this is a current packaging issue.Expected Result
The
workerdandworkerexport conditions should not resolve to code that re-exports@sentry/node.Minimal fix — remove misleading conditions:
Remove the
workerdandworkerexport conditions frompackage.json, since the package does not currently provide Workers-compatible server code. This is a packaging stopgap, not a fully non-breaking resolution:browser(e.g., Vite with['workerd', 'worker', 'browser', ...]) will fall through toindex.client.js, which is safe. But this is not guaranteed across all resolvers — Node's package docs recommend adefaultbranch for unknown runtimes. Whether to adddefaultpointing to the client entry is a design call for the Sentry team.browser/client entry exports stubs forwrapMiddlewaresWithSentry,sentryGlobalRequestMiddleware, andsentryGlobalFunctionMiddleware, but it does not exportwrapFetchWithSentry. Consumers who import that helper would get a build error. The sharedindex.types.tsstill re-exports the full server API surface, so TypeScript types and runtime exports would diverge for Workers consumers.Despite these caveats, removing the conditions is strictly better than the current state: it stops actively directing Workers bundlers to Node code, and the practical impact is limited since the server helpers don't work on Workers anyway.
Longer-term — proper Workers entry (follow-up):
A proper fix would create Worker-specific server modules that use
@sentry/cloudflareinstead of@sentry/node. This is non-trivial since@sentry/nodeis imported directly by multiple server source files, not just the barrel. This would likely be a separate design effort, potentially tracked alongside JS-1388.Actual Result
Worker crashes with
"Cannot initialize ExportedHandler"— silent module evaluation failure, no stack trace, no useful output fromwrangler tail.workerdindex.server.js@sentry/node+ OpenTelemetry +node:*workerindex.server.js@sentry/node+ OpenTelemetry +node:*browserindex.client.js@sentry/browser(no Node deps)nodeindex.server.js@sentry/nodeWorkaround: Replace
@sentry/tanstackstart-reactwith@sentry/reactfor runtime imports. Both exportinit,ErrorBoundary, andtanstackRouterBrowserTracingIntegration. This preserves client-side Sentry but loses the TanStack Start server helpers. For server-side Workers tracking, use@sentry/cloudflareseparately. The Vite plugin (@sentry/tanstackstart-react/vite) is build-time only and unaffected.Related issues
@sentry/nextjs)@sentry/nextjson Cloudflare Workers (same class of bug)Additional context
Note: We are aware the SDK setup docs note this is still alpha and warn that the setup "does not currently work for Cloudflare deployments." This issue is specifically about the misleading
workerd/workerexport conditions — they signal bundler-level compatibility that doesn't exist, causing a silent failure mode that is very difficult to diagnose.Environment details: Cloudflare Workers paid plan, compatibility date
2025-09-01,nodejs_compatenabled. Bundling via Vite 7 (Rolldown) with NitronoExternals: true.We observed platform-dependent behavior: macOS local builds sometimes tree-shook enough undici code for the Worker to boot, while Linux CI included the full transport (~900 KiB), causing module evaluation failure. This variance is secondary to the export-map mismatch but made diagnosis significantly harder.