diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/.gitignore b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/.gitignore
new file mode 100644
index 000000000000..f67821b00540
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/.gitignore
@@ -0,0 +1,6 @@
+node_modules
+dist
+.output
+.wrangler
+.tanstack
+src/routeTree.gen.ts
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/package.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/package.json
new file mode 100644
index 000000000000..b5450d0e198c
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/package.json
@@ -0,0 +1,44 @@
+{
+ "name": "tanstackstart-react-cloudflare",
+ "private": true,
+ "version": "0.0.1",
+ "type": "module",
+ "scripts": {
+ "dev": "vite dev",
+ "build": "vite build",
+ "preview": "wrangler dev --var E2E_TEST_DSN:$E2E_TEST_DSN --log-level=$(test $CI && echo 'none' || echo 'log')",
+ "test": "playwright test",
+ "typecheck": "tsc --noEmit",
+ "test:build": "pnpm install && pnpm build",
+ "test:assert": "pnpm typecheck && pnpm test"
+ },
+ "dependencies": {
+ "@sentry/browser": "file:../../packed/sentry-browser-packed.tgz",
+ "@sentry/cloudflare": "file:../../packed/sentry-cloudflare-packed.tgz",
+ "@sentry/tanstackstart-react": "file:../../packed/sentry-tanstackstart-react-packed.tgz",
+ "@tanstack/react-start": "^1.136.0",
+ "@tanstack/react-router": "^1.136.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0"
+ },
+ "devDependencies": {
+ "@cloudflare/vite-plugin": "^1.35.0",
+ "@cloudflare/workers-types": "^4.20260504.0",
+ "@playwright/test": "~1.56.0",
+ "@sentry-internal/test-utils": "link:../../../test-utils",
+ "@types/react": "^19.2.0",
+ "@types/react-dom": "^19.2.0",
+ "@vitejs/plugin-react": "^4.5.0",
+ "typescript": "^5.9.0",
+ "vite": "7.3.1",
+ "vite-tsconfig-paths": "^5.1.4",
+ "wrangler": "^4.68.1"
+ },
+ "volta": {
+ "node": "24.15.0",
+ "extends": "../../package.json"
+ },
+ "sentryTest": {
+ "optional": true
+ }
+}
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/playwright.config.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/playwright.config.ts
new file mode 100644
index 000000000000..94d9558b37b6
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/playwright.config.ts
@@ -0,0 +1,6 @@
+import { getPlaywrightConfig } from '@sentry-internal/test-utils';
+
+export default getPlaywrightConfig({
+ startCommand: 'pnpm preview',
+ port: 8787,
+});
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/env.d.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/env.d.ts
new file mode 100644
index 000000000000..eb80bafb4834
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/env.d.ts
@@ -0,0 +1,3 @@
+interface Env {
+ E2E_TEST_DSN: string;
+}
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/router.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/router.tsx
new file mode 100644
index 000000000000..c18a1a0b8167
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/router.tsx
@@ -0,0 +1,23 @@
+import * as Sentry from '@sentry/browser';
+import { createRouter } from '@tanstack/react-router';
+import { routeTree } from './routeTree.gen';
+
+export const getRouter = () => {
+ const router = createRouter({
+ routeTree,
+ scrollRestoration: true,
+ });
+
+ if (!router.isServer) {
+ Sentry.init({
+ environment: 'qa',
+ dsn: 'https://public@dsn.ingest.sentry.io/1337',
+ integrations: [Sentry.browserTracingIntegration()],
+ tracesSampleRate: 1.0,
+ release: 'e2e-test',
+ tunnel: 'http://localhost:3031/',
+ });
+ }
+
+ return router;
+};
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/__root.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/__root.tsx
new file mode 100644
index 000000000000..bc3a376d7eba
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/__root.tsx
@@ -0,0 +1,52 @@
+import type { ReactNode } from 'react';
+import { Outlet, createRootRoute, HeadContent, Scripts } from '@tanstack/react-router';
+import { getTraceData } from '@sentry/tanstackstart-react';
+
+export const Route = createRootRoute({
+ head: () => {
+ const traceData = getTraceData();
+ const sentryMeta = Object.entries(traceData).map(([key, value]) => ({
+ name: key,
+ content: value,
+ }));
+
+ return {
+ meta: [
+ {
+ charSet: 'utf-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1',
+ },
+ {
+ title: 'TanStack Start Cloudflare E2E Test',
+ },
+ ...sentryMeta,
+ ],
+ };
+ },
+ component: RootComponent,
+});
+
+function RootComponent() {
+ return (
+
+
+
+ );
+}
+
+function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
+ return (
+
+
+
+
+
+ {children}
+
+
+
+ );
+}
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/api.error.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/api.error.ts
new file mode 100644
index 000000000000..041fb175c1f1
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/api.error.ts
@@ -0,0 +1,11 @@
+import { createFileRoute } from '@tanstack/react-router';
+
+export const Route = createFileRoute('/api/error')({
+ server: {
+ handlers: {
+ GET: async () => {
+ throw new Error('Sentry API Route Test Error');
+ },
+ },
+ },
+});
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/api.flush.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/api.flush.ts
new file mode 100644
index 000000000000..b8f2313504e1
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/api.flush.ts
@@ -0,0 +1,13 @@
+import { createFileRoute } from '@tanstack/react-router';
+import { flush } from '@sentry/cloudflare';
+
+export const Route = createFileRoute('/api/flush')({
+ server: {
+ handlers: {
+ GET: async () => {
+ await flush();
+ return new Response('ok');
+ },
+ },
+ },
+});
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/index.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/index.tsx
new file mode 100644
index 000000000000..5be8873475ef
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/index.tsx
@@ -0,0 +1,31 @@
+import { createFileRoute } from '@tanstack/react-router';
+
+export const Route = createFileRoute('/')({
+ component: Home,
+});
+
+function Home() {
+ return (
+
+
TanStack Start Cloudflare E2E Test
+
+
+
+ );
+}
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/ssr-error.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/ssr-error.tsx
new file mode 100644
index 000000000000..71ba7ce92d29
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/routes/ssr-error.tsx
@@ -0,0 +1,8 @@
+import { createFileRoute } from '@tanstack/react-router';
+
+export const Route = createFileRoute('/ssr-error')({
+ loader: () => {
+ throw new Error('Sentry SSR Test Error');
+ },
+ component: () => SSR Error Page
,
+});
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/server.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/server.ts
new file mode 100644
index 000000000000..54bf854cba88
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/server.ts
@@ -0,0 +1,13 @@
+import * as Sentry from '@sentry/cloudflare';
+import handler from '@tanstack/react-start/server-entry';
+
+export default Sentry.withSentry(
+ (env: Env) => ({
+ dsn: env.E2E_TEST_DSN,
+ tunnel: 'http://localhost:3031/',
+ tracesSampleRate: 1.0,
+ environment: 'qa',
+ }),
+ // @ts-expect-error - handler is not typed as a Cloudflare handler
+ handler,
+);
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/start.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/start.ts
new file mode 100644
index 000000000000..719869f235ef
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/start.ts
@@ -0,0 +1,9 @@
+import { sentryGlobalFunctionMiddleware, sentryGlobalRequestMiddleware } from '@sentry/tanstackstart-react';
+import { createStart } from '@tanstack/react-start';
+
+export const startInstance = createStart(() => {
+ return {
+ requestMiddleware: [sentryGlobalRequestMiddleware],
+ functionMiddleware: [sentryGlobalFunctionMiddleware],
+ };
+});
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/start-event-proxy.mjs
new file mode 100644
index 000000000000..14ed61c3b9bd
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/start-event-proxy.mjs
@@ -0,0 +1,6 @@
+import { startEventProxyServer } from '@sentry-internal/test-utils';
+
+startEventProxyServer({
+ port: 3031,
+ proxyServerName: 'tanstackstart-react-cloudflare',
+});
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/index.test.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/index.test.ts
new file mode 100644
index 000000000000..30daeaedc7fd
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/index.test.ts
@@ -0,0 +1,103 @@
+import { expect, test } from '@playwright/test';
+import { waitForError, waitForTransaction } from '@sentry-internal/test-utils';
+
+test('Sends client-side error to Sentry', async ({ page }) => {
+ const errorEventPromise = waitForError('tanstackstart-react-cloudflare', errorEvent => {
+ return errorEvent?.exception?.values?.[0]?.value === 'Sentry Client Test Error';
+ });
+
+ await page.goto(`/`);
+
+ await expect(page.locator('#client-error-btn')).toBeVisible();
+
+ await page.locator('#client-error-btn').click();
+
+ const errorEvent = await errorEventPromise;
+
+ expect(errorEvent.exception?.values?.[0]).toEqual({
+ type: 'Error',
+ value: 'Sentry Client Test Error',
+ stacktrace: expect.objectContaining({
+ frames: expect.any(Array),
+ }),
+ mechanism: {
+ type: 'auto.browser.global_handlers.onerror',
+ handled: false,
+ },
+ });
+
+ expect(errorEvent.transaction).toBe('/');
+ expect(errorEvent.contexts?.trace?.trace_id).toEqual(expect.any(String));
+ expect(errorEvent.contexts?.trace?.span_id).toEqual(expect.any(String));
+});
+
+test('Sends API route error to Sentry', async ({ page }) => {
+ const errorEventPromise = waitForError('tanstackstart-react-cloudflare', errorEvent => {
+ return errorEvent?.exception?.values?.[0]?.value === 'Sentry API Route Test Error';
+ });
+
+ await page.goto('/');
+
+ await expect(page.locator('#api-error-btn')).toBeVisible();
+
+ await page.locator('#api-error-btn').click();
+
+ const errorEvent = await errorEventPromise;
+
+ expect(errorEvent.exception?.values?.[0]).toEqual({
+ type: 'Error',
+ value: 'Sentry API Route Test Error',
+ stacktrace: expect.objectContaining({
+ frames: expect.any(Array),
+ }),
+ mechanism: {
+ type: 'auto.middleware.tanstackstart.request',
+ handled: false,
+ },
+ });
+});
+
+test('Sends server-side transaction for fetch request', async ({ baseURL }) => {
+ const transactionEventPromise = waitForTransaction('tanstackstart-react-cloudflare', transactionEvent => {
+ return transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /';
+ });
+
+ await fetch(`${baseURL}/`);
+
+ const transactionEvent = await transactionEventPromise;
+
+ expect(transactionEvent.transaction).toBe('GET /');
+ expect(transactionEvent.contexts?.trace).toEqual({
+ trace_id: expect.any(String),
+ span_id: expect.any(String),
+ op: 'http.server',
+ origin: 'auto.http.cloudflare',
+ status: 'ok',
+ data: expect.objectContaining({
+ 'sentry.origin': 'auto.http.cloudflare',
+ 'sentry.op': 'http.server',
+ }),
+ });
+});
+
+test('Propagates trace from server to client', async ({ page }) => {
+ const serverTransactionPromise = waitForTransaction('tanstackstart-react-cloudflare', transactionEvent => {
+ return transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /';
+ });
+
+ const clientTransactionPromise = waitForTransaction('tanstackstart-react-cloudflare', transactionEvent => {
+ return transactionEvent?.contexts?.trace?.op === 'pageload' && transactionEvent?.transaction === '/';
+ });
+
+ await page.goto('/');
+
+ const serverTransaction = await serverTransactionPromise;
+ const clientTransaction = await clientTransactionPromise;
+
+ const serverTraceId = serverTransaction.contexts?.trace?.trace_id;
+ const clientTraceId = clientTransaction.contexts?.trace?.trace_id;
+
+ expect(serverTraceId).toEqual(expect.any(String));
+ expect(clientTraceId).toEqual(expect.any(String));
+ expect(clientTraceId).toBe(serverTraceId);
+});
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tsconfig.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tsconfig.json
new file mode 100644
index 000000000000..ecf9f5694249
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "useDefineForClassFields": true,
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "types": ["@cloudflare/workers-types"]
+ },
+ "include": ["src"]
+}
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/vite.config.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/vite.config.ts
new file mode 100644
index 000000000000..8e749133c7d8
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/vite.config.ts
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import tsConfigPaths from 'vite-tsconfig-paths';
+import { tanstackStart } from '@tanstack/react-start/plugin/vite';
+import viteReact from '@vitejs/plugin-react';
+import { cloudflare } from '@cloudflare/vite-plugin';
+
+export default defineConfig({
+ server: {
+ port: 3030,
+ },
+ plugins: [cloudflare({ viteEnvironment: { name: 'ssr' } }), tsConfigPaths(), tanstackStart(), viteReact()],
+});
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/wrangler.jsonc b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/wrangler.jsonc
new file mode 100644
index 000000000000..cea7ef58657d
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/wrangler.jsonc
@@ -0,0 +1,10 @@
+{
+ "$schema": "node_modules/wrangler/config-schema.json",
+ "name": "tanstackstart-react-cloudflare",
+ "compatibility_date": "2026-05-04",
+ "compatibility_flags": ["nodejs_compat"],
+ "main": "src/server.ts",
+ "observability": {
+ "enabled": true,
+ },
+}