diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/.gitignore b/dev-packages/e2e-tests/test-applications/tanstackstart-react/.gitignore
new file mode 100644
index 000000000000..a547bf36d8d1
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/.npmrc b/dev-packages/e2e-tests/test-applications/tanstackstart-react/.npmrc
new file mode 100644
index 000000000000..070f80f05092
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/.npmrc
@@ -0,0 +1,2 @@
+@sentry:registry=http://127.0.0.1:4873
+@sentry-internal:registry=http://127.0.0.1:4873
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs b/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs
new file mode 100644
index 000000000000..8bc20de7578b
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs
@@ -0,0 +1,12 @@
+import * as Sentry from '@sentry/tanstackstart-react';
+
+Sentry.init({
+ environment: 'qa', // dynamic sampling bias to keep transactions
+ dsn: process.env.E2E_TEST_DSN,
+ tunnel: `http://localhost:3031/`, // proxy server
+ tracesSampleRate: 1,
+ transportOptions: {
+ // We expect the app to send a lot of events in a short time
+ bufferSize: 1000,
+ },
+});
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json
new file mode 100644
index 000000000000..e44229cce78f
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json
@@ -0,0 +1,38 @@
+{
+ "name": "tanstackstart-react",
+ "private": true,
+ "version": "0.0.1",
+ "type": "module",
+ "scripts": {
+ "build": "vite build && cp instrument.server.mjs .output/server",
+ "start": "node --import ./.output/server/instrument.server.mjs .output/server/index.mjs",
+ "test": "playwright test",
+ "clean": "npx rimraf node_modules pnpm-lock.yaml",
+ "test:build": "pnpm install && pnpm build",
+ "test:assert": "pnpm test"
+ },
+ "dependencies": {
+ "@sentry/tanstackstart-react": "latest || *",
+ "@tanstack/react-start": "^1.139.12",
+ "@tanstack/react-router": "^1.139.12",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0"
+ },
+ "devDependencies": {
+ "@types/react": "^19.2.0",
+ "@types/react-dom": "^19.2.0",
+ "@types/node": "^24.10.0",
+ "@typescript-eslint/eslint-plugin": "^7.2.0",
+ "@typescript-eslint/parser": "^7.2.0",
+ "@vitejs/plugin-react-swc": "^3.5.0",
+ "typescript": "^5.9.0",
+ "vite": "7.2.0",
+ "vite-tsconfig-paths": "^5.1.4",
+ "nitro": "^3.0.0",
+ "@playwright/test": "~1.53.2",
+ "@sentry-internal/test-utils": "link:../../../test-utils"
+ },
+ "volta": {
+ "extends": "../../package.json"
+ }
+}
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/tanstackstart-react/playwright.config.mjs
new file mode 100644
index 000000000000..4ca3c24e7fda
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/playwright.config.mjs
@@ -0,0 +1,8 @@
+import { getPlaywrightConfig } from '@sentry-internal/test-utils';
+
+const config = getPlaywrightConfig({
+ startCommand: `pnpm start`,
+ port: 3000,
+});
+
+export default config;
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx
new file mode 100644
index 000000000000..b1c6f7727a26
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx
@@ -0,0 +1,25 @@
+import * as Sentry from '@sentry/tanstackstart-react';
+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', // dynamic sampling bias to keep transactions
+ dsn: 'https://public@dsn.ingest.sentry.io/1337',
+ integrations: [Sentry.tanstackRouterBrowserTracingIntegration(router)],
+ // We recommend adjusting this value in production, or using tracesSampler
+ // for finer control
+ tracesSampleRate: 1.0,
+ release: 'e2e-test',
+ tunnel: 'http://localhost:3031/', // proxy server
+ });
+ }
+
+ return router;
+};
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/__root.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/__root.tsx
new file mode 100644
index 000000000000..0a268a350e34
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/__root.tsx
@@ -0,0 +1,42 @@
+import type { ReactNode } from 'react';
+import { Outlet, createRootRoute, HeadContent, Scripts } from '@tanstack/react-router';
+
+export const Route = createRootRoute({
+ head: () => ({
+ meta: [
+ {
+ charSet: 'utf-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1',
+ },
+ {
+ title: 'TanStack Start Starter',
+ },
+ ],
+ }),
+ component: RootComponent,
+});
+
+function RootComponent() {
+ return (
+
+
+
+ );
+}
+
+function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
+ return (
+
+
+
+
+
+ {children}
+
+
+
+ );
+}
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts
new file mode 100644
index 000000000000..470d53346ad7
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts
@@ -0,0 +1,17 @@
+import * as Sentry from '@sentry/tanstackstart-react';
+import { createFileRoute } from '@tanstack/react-router';
+
+export const Route = createFileRoute('/api/error')({
+ server: {
+ handlers: {
+ GET: async () => {
+ try {
+ throw new Error('Sentry API Route Test Error');
+ } catch (error) {
+ Sentry.captureException(error);
+ throw error;
+ }
+ },
+ },
+ },
+});
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx
new file mode 100644
index 000000000000..a92fabf20c4a
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx
@@ -0,0 +1,41 @@
+import { createFileRoute } from '@tanstack/react-router';
+import { createServerFn } from '@tanstack/react-start';
+
+const throwServerError = createServerFn().handler(async () => {
+ throw new Error('Sentry Server Function Test Error');
+});
+
+export const Route = createFileRoute('/')({
+ component: Home,
+});
+
+function Home() {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/tanstackstart-react/start-event-proxy.mjs
new file mode 100644
index 000000000000..a3f8045010bd
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/start-event-proxy.mjs
@@ -0,0 +1,6 @@
+import { startEventProxyServer } from '@sentry-internal/test-utils';
+
+startEventProxyServer({
+ port: 3031,
+ proxyServerName: 'tanstackstart-react',
+});
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts
new file mode 100644
index 000000000000..f5d25febb7a4
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts
@@ -0,0 +1,92 @@
+import { expect, test } from '@playwright/test';
+import { waitForError } from '@sentry-internal/test-utils';
+
+test('Sends client-side error to Sentry with auto-instrumentation', async ({ page }) => {
+ const errorEventPromise = waitForError('tanstackstart-react', errorEvent => {
+ return errorEvent?.exception?.values?.[0]?.value === 'Sentry Client Test Error';
+ });
+
+ await page.goto(`/`);
+
+ await expect(page.locator('button').filter({ hasText: 'Break the client' })).toBeVisible();
+
+ await page.locator('button').filter({ hasText: 'Break the client' }).click();
+
+ const errorEvent = await errorEventPromise;
+
+ expect(errorEvent).toMatchObject({
+ exception: {
+ values: [
+ {
+ type: 'Error',
+ value: 'Sentry Client Test Error',
+ mechanism: {
+ handled: false,
+ },
+ },
+ ],
+ },
+ });
+
+ expect(errorEvent.transaction).toBe('/');
+});
+
+test('Sends server-side function error to Sentry with auto-instrumentation', async ({ page }) => {
+ const errorEventPromise = waitForError('tanstackstart-react', errorEvent => {
+ return errorEvent?.exception?.values?.[0]?.value === 'Sentry Server Function Test Error';
+ });
+
+ await page.goto(`/`);
+
+ await expect(page.locator('button').filter({ hasText: 'Break server function' })).toBeVisible();
+
+ await page.locator('button').filter({ hasText: 'Break server function' }).click();
+
+ const errorEvent = await errorEventPromise;
+
+ expect(errorEvent).toMatchObject({
+ exception: {
+ values: [
+ {
+ type: 'Error',
+ value: 'Sentry Server Function Test Error',
+ mechanism: {
+ handled: false,
+ },
+ },
+ ],
+ },
+ });
+
+ expect(errorEvent.transaction).toBe('/');
+});
+
+test('Sends API route error to Sentry if manually instrumented', async ({ page }) => {
+ const errorEventPromise = waitForError('tanstackstart-react', errorEvent => {
+ return errorEvent?.exception?.values?.[0]?.value === 'Sentry API Route Test Error';
+ });
+
+ await page.goto(`/`);
+
+ await expect(page.locator('button').filter({ hasText: 'Break API route' })).toBeVisible();
+
+ await page.locator('button').filter({ hasText: 'Break API route' }).click();
+
+ const errorEvent = await errorEventPromise;
+
+ expect(errorEvent).toMatchObject({
+ exception: {
+ values: [
+ {
+ type: 'Error',
+ value: 'Sentry API Route Test Error',
+ mechanism: {
+ handled: true,
+ },
+ },
+ ],
+ },
+ });
+
+ expect(errorEvent.transaction).toBe('GET /api/error');
+});
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.json
new file mode 100644
index 000000000000..5dcdb1fa6f4a
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "useDefineForClassFields": true,
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "strictNullChecks": true
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.node.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.node.json
new file mode 100644
index 000000000000..97ede7ee6f2d
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts
new file mode 100644
index 000000000000..4df9fbb14208
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts
@@ -0,0 +1,18 @@
+import { defineConfig } from 'vite';
+import tsConfigPaths from 'vite-tsconfig-paths';
+import { tanstackStart } from '@tanstack/react-start/plugin/vite';
+import viteReact from '@vitejs/plugin-react-swc';
+import { nitro } from 'nitro/vite';
+
+export default defineConfig({
+ server: {
+ port: 3000,
+ },
+ plugins: [
+ tsConfigPaths(),
+ tanstackStart(),
+ nitro(),
+ // react's vite plugin must come after start's vite plugin
+ viteReact(),
+ ],
+});