Repository navigation
fix(tanstackstart-react): workerd/worker export conditions resolve to @sentry/node, breaking Cloudflare Workers #20038
Description
Is there an existing issue for this?
- I have checked for existing issues https://github.com/getsentry/sentry-javascript/issues
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, andnodeall resolve toindex.server.js - Inspect
build/esm/index.server.js— doesexport * from '@sentry/node'
For the runtime failure:
- Create a TanStack Start app deployed to Cloudflare Workers (Nitro
cloudflare-modulepreset,noExternals: true) - Install
@sentry/[email protected] - 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:
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/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 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. - Export surface change. The
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/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/nextjson 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.
Metadata
Metadata
Assignees
Projects
- StatusShow more project fieldsWaiting for: Community
Activity
linear-code commentedon Mar 30, 2026
JS-2022
fix(tanstackstart-react): remove misleading `workerd`/`worker` export…
[-]fix(tanstackstart-react): \`workerd\`/\`worker\` export conditions resolve to \`@sentry/node\`, breaking Cloudflare Workers[/-][+]fix(tanstackstart-react): workerd/worker export conditions resolve to @sentry/node, breaking Cloudflare Workers[/+]jmalmo commentedon Mar 30, 2026
Our PR (#20039) was auto-closed by the bot. The fix is a one-liner — removing the
workerd/workerconditions frompackages/tanstackstart-react/package.json(8 lines deleted, no new code). The branch is available atjmalmo/sentry-javascript:fix/tanstackstart-react-remove-misleading-worker-exportsif useful.Happy to reopen the PR or adjust the approach if the team prefers a different direction (e.g., adding a
defaultfallback to the client entry, or bundling this into the broader #18669 effort).JPeer264 commentedon Mar 30, 2026
Hey @jmalmo we recently added that exports. Do you have a minimal repro available that causes this? The
@sentry/nodeSDK within Cloudflare Workers should actually work.jmalmo commentedon Mar 30, 2026
@JPeer264 Here's a minimal repro:
https://github.com/jmalmo/sentry-tanstackstart-workers-repro
It's a bare TanStack Start app with Nitro's
cloudflare-modulepreset (noExternals: true). The only Sentry import isimport * as Sentry from '@sentry/tanstackstart-react'inrouter.tsx.The build analysis shows the router chunk at 1,324 KiB containing
node:http,node:os,node:fs,node:diagnostics_channel,node:zlib,undici, and@opentelemetry/instrumentation— all from@sentry/nodebeing resolved via theworkerdexport condition.Swapping to
import * as Sentry from '@sentry/react'drops the bundle to 923 KiB with zeronode:*references.The key detail: Nitro uses
noExternals: truefor Workers (nonode_modulesat runtime — everything is bundled). So Vite resolves@sentry/tanstackstart-reactusingssr.resolve.conditions(notssr.resolve.externalConditions), and theworkerdcondition routes toindex.server.js→export * from '@sentry/node'.If
@sentry/nodeis intended to work on Workers, the issue may be that the full dependency tree (undici HTTP transport, OpenTelemetry instrumentation) doesn't survive bundling into a single Worker module — but the export map is what causes it to be pulled in.12 remaining items
getsantry commentedon Apr 23, 2026
This issue has gone three weeks without activity. In another week, I will close it.
But! If you comment or otherwise update it, I will reset the clock, and if you remove the label
Waiting for: Community, I will leave it alone ... forever!"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀
feat: monitoring/sentry recipe (@sentry/cloudflare + @sentry/react + …
feat(obs): wire Sentry into web app and worker with same-origin tunnel
feat(f311x): add worker-side Sentry error monitoring (@sentry/cloudfl…
feat(observability): クライアント側のエラーを収集できるようにする(Sentry) (#382)
docs(deployment): Sentry のセットアップ手順の誤りを直し、ウィザードの落とし穴を書く (#488)