From 95708f20a45c9a0ec204bfa06eec7c5dab01fdcd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=9D=B4=EC=A2=85=EA=B2=BD?= <gyoung3063413@naver.com>
Date: Sun, 4 Jan 2026 19:28:13 +0900
Subject: [PATCH 1/5] fix: update cleanPath to replace pipe characters with
 encoded value

---
 packages/router-core/src/path.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/router-core/src/path.ts b/packages/router-core/src/path.ts
index 859a900496..4243d52d82 100644
--- a/packages/router-core/src/path.ts
+++ b/packages/router-core/src/path.ts
@@ -22,7 +22,7 @@ export function joinPaths(paths: Array<string | undefined>) {
 /** Remove repeated slashes from a path string. */
 export function cleanPath(path: string) {
   // remove double slashes
-  return path.replace(/\/{2,}/g, '/')
+  return path.replace(/\/{2,}/g, '/').replace(/\|/g, '%7C')
 }
 
 /** Trim leading slashes (except preserving root '/'). */

From 6d1ae3e58cb9bb4f952f4c4d7100249249667edf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=9D=B4=EC=A2=85=EA=B2=BD?= <gyoung3063413@naver.com>
Date: Sun, 4 Jan 2026 19:36:15 +0900
Subject: [PATCH 2/5] feat: add route for special character pipe in path and
 corresponding tests

---
 .../basic-file-based/src/routeTree.gen.ts     | 21 +++++++++++++++++++
 .../src/routes/special|pipe.tsx               |  5 +++++
 .../basic-file-based/tests/app.spec.ts        | 13 ++++++++++++
 3 files changed, 39 insertions(+)
 create mode 100644 e2e/react-router/basic-file-based/src/routes/special|pipe.tsx

diff --git a/e2e/react-router/basic-file-based/src/routeTree.gen.ts b/e2e/react-router/basic-file-based/src/routeTree.gen.ts
index 28197e4d98..06620f1dc0 100644
--- a/e2e/react-router/basic-file-based/src/routeTree.gen.ts
+++ b/e2e/react-router/basic-file-based/src/routeTree.gen.ts
@@ -9,6 +9,7 @@
 // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
 
 import { Route as rootRouteImport } from './routes/__root'
+import { Route as SpecialChar124pipeRouteImport } from './routes/special|pipe'
 import { Route as RemountDepsRouteImport } from './routes/remountDeps'
 import { Route as PostsRouteImport } from './routes/posts'
 import { Route as NotRemountDepsRouteImport } from './routes/notRemountDeps'
@@ -118,6 +119,11 @@ import { Route as NonNestedDeepBazBarFooRouteRouteImport } from './routes/non-ne
 import { Route as NonNestedDeepBazBarFooIndexRouteImport } from './routes/non-nested/deep/$baz_.bar.$foo.index'
 import { Route as NonNestedDeepBazBarFooQuxRouteImport } from './routes/non-nested/deep/$baz_.bar.$foo_.qux'
 
+const SpecialChar124pipeRoute = SpecialChar124pipeRouteImport.update({
+  id: '/special|pipe',
+  path: '/special|pipe',
+  getParentRoute: () => rootRouteImport,
+} as any)
 const RemountDepsRoute = RemountDepsRouteImport.update({
   id: '/remountDeps',
   path: '/remountDeps',
@@ -715,6 +721,7 @@ export interface FileRoutesByFullPath {
   '/notRemountDeps': typeof NotRemountDepsRoute
   '/posts': typeof PostsRouteWithChildren
   '/remountDeps': typeof RemountDepsRoute
+  '/special|pipe': typeof SpecialChar124pipeRoute
   '/non-nested/deep': typeof NonNestedDeepRouteRouteWithChildren
   '/non-nested/named': typeof NonNestedNamedRouteRouteWithChildren
   '/non-nested/path': typeof NonNestedPathRouteRouteWithChildren
@@ -819,6 +826,7 @@ export interface FileRoutesByTo {
   '/masks': typeof MasksRouteWithChildren
   '/notRemountDeps': typeof NotRemountDepsRoute
   '/remountDeps': typeof RemountDepsRoute
+  '/special|pipe': typeof SpecialChar124pipeRoute
   '/non-nested/deep': typeof NonNestedDeepRouteRouteWithChildren
   '/non-nested/named': typeof NonNestedNamedRouteRouteWithChildren
   '/non-nested/path': typeof NonNestedPathRouteRouteWithChildren
@@ -918,6 +926,7 @@ export interface FileRoutesById {
   '/notRemountDeps': typeof NotRemountDepsRoute
   '/posts': typeof PostsRouteWithChildren
   '/remountDeps': typeof RemountDepsRoute
+  '/special|pipe': typeof SpecialChar124pipeRoute
   '/non-nested/deep': typeof NonNestedDeepRouteRouteWithChildren
   '/non-nested/named': typeof NonNestedNamedRouteRouteWithChildren
   '/non-nested/path': typeof NonNestedPathRouteRouteWithChildren
@@ -1029,6 +1038,7 @@ export interface FileRouteTypes {
     | '/notRemountDeps'
     | '/posts'
     | '/remountDeps'
+    | '/special|pipe'
     | '/non-nested/deep'
     | '/non-nested/named'
     | '/non-nested/path'
@@ -1133,6 +1143,7 @@ export interface FileRouteTypes {
     | '/masks'
     | '/notRemountDeps'
     | '/remountDeps'
+    | '/special|pipe'
     | '/non-nested/deep'
     | '/non-nested/named'
     | '/non-nested/path'
@@ -1231,6 +1242,7 @@ export interface FileRouteTypes {
     | '/notRemountDeps'
     | '/posts'
     | '/remountDeps'
+    | '/special|pipe'
     | '/non-nested/deep'
     | '/non-nested/named'
     | '/non-nested/path'
@@ -1342,6 +1354,7 @@ export interface RootRouteChildren {
   NotRemountDepsRoute: typeof NotRemountDepsRoute
   PostsRoute: typeof PostsRouteWithChildren
   RemountDepsRoute: typeof RemountDepsRoute
+  SpecialChar124pipeRoute: typeof SpecialChar124pipeRoute
   ParamsPsNonNestedRouteRoute: typeof ParamsPsNonNestedRouteRouteWithChildren
   RelativeLinkRouteRoute: typeof RelativeLinkRouteRouteWithChildren
   RelativeUseNavigateRouteRoute: typeof RelativeUseNavigateRouteRouteWithChildren
@@ -1374,6 +1387,13 @@ export interface RootRouteChildren {
 
 declare module '@tanstack/react-router' {
   interface FileRoutesByPath {
+    '/special|pipe': {
+      id: '/special|pipe'
+      path: '/special|pipe'
+      fullPath: '/special|pipe'
+      preLoaderRoute: typeof SpecialChar124pipeRouteImport
+      parentRoute: typeof rootRouteImport
+    }
     '/remountDeps': {
       id: '/remountDeps'
       path: '/remountDeps'
@@ -2598,6 +2618,7 @@ const rootRouteChildren: RootRouteChildren = {
   NotRemountDepsRoute: NotRemountDepsRoute,
   PostsRoute: PostsRouteWithChildren,
   RemountDepsRoute: RemountDepsRoute,
+  SpecialChar124pipeRoute: SpecialChar124pipeRoute,
   ParamsPsNonNestedRouteRoute: ParamsPsNonNestedRouteRouteWithChildren,
   RelativeLinkRouteRoute: RelativeLinkRouteRouteWithChildren,
   RelativeUseNavigateRouteRoute: RelativeUseNavigateRouteRouteWithChildren,
diff --git a/e2e/react-router/basic-file-based/src/routes/special|pipe.tsx b/e2e/react-router/basic-file-based/src/routes/special|pipe.tsx
new file mode 100644
index 0000000000..e8b6e4e567
--- /dev/null
+++ b/e2e/react-router/basic-file-based/src/routes/special|pipe.tsx
@@ -0,0 +1,5 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/special|pipe')({
+  component: () => <div>Hello /special|pipe!</div>,
+})
diff --git a/e2e/react-router/basic-file-based/tests/app.spec.ts b/e2e/react-router/basic-file-based/tests/app.spec.ts
index f644c10042..2f6d0ccb88 100644
--- a/e2e/react-router/basic-file-based/tests/app.spec.ts
+++ b/e2e/react-router/basic-file-based/tests/app.spec.ts
@@ -394,3 +394,16 @@ test.describe('Pathless layout routes', () => {
     await expect(page.locator('body')).toContainText('Not Found')
   })
 })
+
+test.describe('Special characters in route paths', () => {
+  test('should render route with pipe character in path', async ({
+    page,
+    baseURL,
+  }) => {
+    await page.goto('/special|pipe')
+
+    await expect(page.locator('body')).toContainText('Hello /special|pipe!')
+
+    expect(page.url()).toBe(`${baseURL}/special%7Cpipe`)
+  })
+})

From 4eaf78d86c3bd10ed5ad37d75d5019eb49f57a6b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=9D=B4=EC=A2=85=EA=B2=BD?= <gyoung3063413@naver.com>
Date: Wed, 7 Jan 2026 21:00:26 +0900
Subject: [PATCH 3/5] feat: add route and tests for handling pipe character in
 path

---
 e2e/react-start/basic/src/routeTree.gen.ts    | 21 ++++++++++++++++
 e2e/react-start/basic/src/routes/__root.tsx   |  9 +++++++
 .../basic/src/routes/pipe.$reference.tsx      | 10 ++++++++
 .../tests/pipe-character-in-path.spec.ts      | 24 +++++++++++++++++++
 4 files changed, 64 insertions(+)
 create mode 100644 e2e/react-start/basic/src/routes/pipe.$reference.tsx
 create mode 100644 e2e/react-start/basic/tests/pipe-character-in-path.spec.ts

diff --git a/e2e/react-start/basic/src/routeTree.gen.ts b/e2e/react-start/basic/src/routeTree.gen.ts
index 27d5e91145..2a72e41265 100644
--- a/e2e/react-start/basic/src/routeTree.gen.ts
+++ b/e2e/react-start/basic/src/routeTree.gen.ts
@@ -42,6 +42,7 @@ import { Route as RawStreamSsrMixedRouteImport } from './routes/raw-stream/ssr-m
 import { Route as RawStreamSsrBinaryHintRouteImport } from './routes/raw-stream/ssr-binary-hint'
 import { Route as RawStreamClientCallRouteImport } from './routes/raw-stream/client-call'
 import { Route as PostsPostIdRouteImport } from './routes/posts.$postId'
+import { Route as PipeReferenceRouteImport } from './routes/pipe.$reference'
 import { Route as NotFoundViaLoaderRouteImport } from './routes/not-found/via-loader'
 import { Route as NotFoundViaBeforeLoadRouteImport } from './routes/not-found/via-beforeLoad'
 import { Route as MultiCookieRedirectTargetRouteImport } from './routes/multi-cookie-redirect/target'
@@ -228,6 +229,11 @@ const PostsPostIdRoute = PostsPostIdRouteImport.update({
   path: '/$postId',
   getParentRoute: () => PostsRoute,
 } as any)
+const PipeReferenceRoute = PipeReferenceRouteImport.update({
+  id: '/pipe/$reference',
+  path: '/pipe/$reference',
+  getParentRoute: () => rootRouteImport,
+} as any)
 const NotFoundViaLoaderRoute = NotFoundViaLoaderRouteImport.update({
   id: '/via-loader',
   path: '/via-loader',
@@ -343,6 +349,7 @@ export interface FileRoutesByFullPath {
   '/multi-cookie-redirect/target': typeof MultiCookieRedirectTargetRoute
   '/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
   '/not-found/via-loader': typeof NotFoundViaLoaderRoute
+  '/pipe/$reference': typeof PipeReferenceRoute
   '/posts/$postId': typeof PostsPostIdRoute
   '/raw-stream/client-call': typeof RawStreamClientCallRoute
   '/raw-stream/ssr-binary-hint': typeof RawStreamSsrBinaryHintRoute
@@ -389,6 +396,7 @@ export interface FileRoutesByTo {
   '/multi-cookie-redirect/target': typeof MultiCookieRedirectTargetRoute
   '/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
   '/not-found/via-loader': typeof NotFoundViaLoaderRoute
+  '/pipe/$reference': typeof PipeReferenceRoute
   '/posts/$postId': typeof PostsPostIdRoute
   '/raw-stream/client-call': typeof RawStreamClientCallRoute
   '/raw-stream/ssr-binary-hint': typeof RawStreamSsrBinaryHintRoute
@@ -441,6 +449,7 @@ export interface FileRoutesById {
   '/multi-cookie-redirect/target': typeof MultiCookieRedirectTargetRoute
   '/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
   '/not-found/via-loader': typeof NotFoundViaLoaderRoute
+  '/pipe/$reference': typeof PipeReferenceRoute
   '/posts/$postId': typeof PostsPostIdRoute
   '/raw-stream/client-call': typeof RawStreamClientCallRoute
   '/raw-stream/ssr-binary-hint': typeof RawStreamSsrBinaryHintRoute
@@ -494,6 +503,7 @@ export interface FileRouteTypes {
     | '/multi-cookie-redirect/target'
     | '/not-found/via-beforeLoad'
     | '/not-found/via-loader'
+    | '/pipe/$reference'
     | '/posts/$postId'
     | '/raw-stream/client-call'
     | '/raw-stream/ssr-binary-hint'
@@ -540,6 +550,7 @@ export interface FileRouteTypes {
     | '/multi-cookie-redirect/target'
     | '/not-found/via-beforeLoad'
     | '/not-found/via-loader'
+    | '/pipe/$reference'
     | '/posts/$postId'
     | '/raw-stream/client-call'
     | '/raw-stream/ssr-binary-hint'
@@ -591,6 +602,7 @@ export interface FileRouteTypes {
     | '/multi-cookie-redirect/target'
     | '/not-found/via-beforeLoad'
     | '/not-found/via-loader'
+    | '/pipe/$reference'
     | '/posts/$postId'
     | '/raw-stream/client-call'
     | '/raw-stream/ssr-binary-hint'
@@ -642,6 +654,7 @@ export interface RootRouteChildren {
   Char45824Char54620Char48124Char44397Route: typeof Char45824Char54620Char48124Char44397Route
   ApiUsersRoute: typeof ApiUsersRouteWithChildren
   MultiCookieRedirectTargetRoute: typeof MultiCookieRedirectTargetRoute
+  PipeReferenceRoute: typeof PipeReferenceRoute
   RedirectTargetRoute: typeof RedirectTargetRouteWithChildren
   MultiCookieRedirectIndexRoute: typeof MultiCookieRedirectIndexRoute
   RedirectIndexRoute: typeof RedirectIndexRoute
@@ -882,6 +895,13 @@ declare module '@tanstack/react-router' {
       preLoaderRoute: typeof PostsPostIdRouteImport
       parentRoute: typeof PostsRoute
     }
+    '/pipe/$reference': {
+      id: '/pipe/$reference'
+      path: '/pipe/$reference'
+      fullPath: '/pipe/$reference'
+      preLoaderRoute: typeof PipeReferenceRouteImport
+      parentRoute: typeof rootRouteImport
+    }
     '/not-found/via-loader': {
       id: '/not-found/via-loader'
       path: '/via-loader'
@@ -1184,6 +1204,7 @@ const rootRouteChildren: RootRouteChildren = {
     Char45824Char54620Char48124Char44397Route,
   ApiUsersRoute: ApiUsersRouteWithChildren,
   MultiCookieRedirectTargetRoute: MultiCookieRedirectTargetRoute,
+  PipeReferenceRoute: PipeReferenceRoute,
   RedirectTargetRoute: RedirectTargetRouteWithChildren,
   MultiCookieRedirectIndexRoute: MultiCookieRedirectIndexRoute,
   RedirectIndexRoute: RedirectIndexRoute,
diff --git a/e2e/react-start/basic/src/routes/__root.tsx b/e2e/react-start/basic/src/routes/__root.tsx
index e1862b499c..145b9ff76d 100644
--- a/e2e/react-start/basic/src/routes/__root.tsx
+++ b/e2e/react-start/basic/src/routes/__root.tsx
@@ -181,6 +181,15 @@ function RootDocument({ children }: { children: React.ReactNode }) {
           >
             Raw Stream
           </Link>{' '}
+          <Link
+            to="/pipe/$reference"
+            params={{ reference: 'hello|world' }}
+            activeProps={{
+              className: 'font-bold',
+            }}
+          >
+            Dynamic Pipe Character
+          </Link>{' '}
           <Link
             // @ts-expect-error
             to="/this-route-does-not-exist"
diff --git a/e2e/react-start/basic/src/routes/pipe.$reference.tsx b/e2e/react-start/basic/src/routes/pipe.$reference.tsx
new file mode 100644
index 0000000000..4efb4d5622
--- /dev/null
+++ b/e2e/react-start/basic/src/routes/pipe.$reference.tsx
@@ -0,0 +1,10 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/pipe/$reference')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  const params = Route.useParams()
+  return <h4>Hello {params.reference}!</h4>
+}
diff --git a/e2e/react-start/basic/tests/pipe-character-in-path.spec.ts b/e2e/react-start/basic/tests/pipe-character-in-path.spec.ts
new file mode 100644
index 0000000000..0c57126c64
--- /dev/null
+++ b/e2e/react-start/basic/tests/pipe-character-in-path.spec.ts
@@ -0,0 +1,24 @@
+import { expect } from '@playwright/test'
+
+import { test } from '@tanstack/router-e2e-utils'
+
+test('encodes pipe character in href for param link', async ({ page }) => {
+  await page.goto('/pipe/hello|world')
+
+  await expect(page.locator('body')).toContainText('Hello hello|world!')
+})
+
+test('direct navigation keeps encoded url after reload', async ({
+  page,
+  baseURL,
+}) => {
+  await page.goto('/pipe/hello|world')
+
+  await expect(page.locator('body')).toContainText('Hello hello|world!')
+  expect(page.url()).toBe(`${baseURL}/pipe/hello%7Cworld`)
+
+  await page.reload()
+
+  await expect(page.locator('body')).toContainText('Hello hello|world!')
+  expect(page.url()).toBe(`${baseURL}/pipe/hello%7Cworld`)
+})

From eab09b669eb785e308c250d1bad6115b72f15b13 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=9D=B4=EC=A2=85=EA=B2=BD?= <gyoung3063413@naver.com>
Date: Sat, 10 Jan 2026 14:28:06 +0900
Subject: [PATCH 4/5] fixup! feat: add route for special character pipe in path
 and corresponding tests

---
 .../basic-file-based/src/routeTree.gen.ts     | 42 +++++++++----------
 .../basic-file-based/src/routes/__root.tsx    |  9 ++++
 .../src/routes/pipe.$reference.tsx            | 10 +++++
 .../src/routes/special|pipe.tsx               |  5 ---
 .../basic-file-based/tests/app.spec.ts        |  6 +--
 5 files changed, 43 insertions(+), 29 deletions(-)
 create mode 100644 e2e/react-router/basic-file-based/src/routes/pipe.$reference.tsx
 delete mode 100644 e2e/react-router/basic-file-based/src/routes/special|pipe.tsx

diff --git a/e2e/react-router/basic-file-based/src/routeTree.gen.ts b/e2e/react-router/basic-file-based/src/routeTree.gen.ts
index 06620f1dc0..d8f74a9b0f 100644
--- a/e2e/react-router/basic-file-based/src/routeTree.gen.ts
+++ b/e2e/react-router/basic-file-based/src/routeTree.gen.ts
@@ -9,7 +9,6 @@
 // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
 
 import { Route as rootRouteImport } from './routes/__root'
-import { Route as SpecialChar124pipeRouteImport } from './routes/special|pipe'
 import { Route as RemountDepsRouteImport } from './routes/remountDeps'
 import { Route as PostsRouteImport } from './routes/posts'
 import { Route as NotRemountDepsRouteImport } from './routes/notRemountDeps'
@@ -34,6 +33,7 @@ import { Route as StructuralSharingEnabledRouteImport } from './routes/structura
 import { Route as SearchParamsDefaultRouteImport } from './routes/search-params/default'
 import { Route as RedirectTargetRouteImport } from './routes/redirect/$target'
 import { Route as PostsPostIdRouteImport } from './routes/posts.$postId'
+import { Route as PipeReferenceRouteImport } from './routes/pipe.$reference'
 import { Route as LayoutLayout2RouteImport } from './routes/_layout/_layout-2'
 import { Route as groupLazyinsideRouteImport } from './routes/(group)/lazyinside'
 import { Route as groupInsideRouteImport } from './routes/(group)/inside'
@@ -119,11 +119,6 @@ import { Route as NonNestedDeepBazBarFooRouteRouteImport } from './routes/non-ne
 import { Route as NonNestedDeepBazBarFooIndexRouteImport } from './routes/non-nested/deep/$baz_.bar.$foo.index'
 import { Route as NonNestedDeepBazBarFooQuxRouteImport } from './routes/non-nested/deep/$baz_.bar.$foo_.qux'
 
-const SpecialChar124pipeRoute = SpecialChar124pipeRouteImport.update({
-  id: '/special|pipe',
-  path: '/special|pipe',
-  getParentRoute: () => rootRouteImport,
-} as any)
 const RemountDepsRoute = RemountDepsRouteImport.update({
   id: '/remountDeps',
   path: '/remountDeps',
@@ -245,6 +240,11 @@ const PostsPostIdRoute = PostsPostIdRouteImport.update({
   path: '/$postId',
   getParentRoute: () => PostsRoute,
 } as any)
+const PipeReferenceRoute = PipeReferenceRouteImport.update({
+  id: '/pipe/$reference',
+  path: '/pipe/$reference',
+  getParentRoute: () => rootRouteImport,
+} as any)
 const LayoutLayout2Route = LayoutLayout2RouteImport.update({
   id: '/_layout-2',
   getParentRoute: () => LayoutRoute,
@@ -721,7 +721,6 @@ export interface FileRoutesByFullPath {
   '/notRemountDeps': typeof NotRemountDepsRoute
   '/posts': typeof PostsRouteWithChildren
   '/remountDeps': typeof RemountDepsRoute
-  '/special|pipe': typeof SpecialChar124pipeRoute
   '/non-nested/deep': typeof NonNestedDeepRouteRouteWithChildren
   '/non-nested/named': typeof NonNestedNamedRouteRouteWithChildren
   '/non-nested/path': typeof NonNestedPathRouteRouteWithChildren
@@ -733,6 +732,7 @@ export interface FileRoutesByFullPath {
   '/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute
   '/inside': typeof groupInsideRoute
   '/lazyinside': typeof groupLazyinsideRoute
+  '/pipe/$reference': typeof PipeReferenceRoute
   '/posts/$postId': typeof PostsPostIdRoute
   '/redirect/$target': typeof RedirectTargetRouteWithChildren
   '/search-params/default': typeof SearchParamsDefaultRoute
@@ -826,7 +826,6 @@ export interface FileRoutesByTo {
   '/masks': typeof MasksRouteWithChildren
   '/notRemountDeps': typeof NotRemountDepsRoute
   '/remountDeps': typeof RemountDepsRoute
-  '/special|pipe': typeof SpecialChar124pipeRoute
   '/non-nested/deep': typeof NonNestedDeepRouteRouteWithChildren
   '/non-nested/named': typeof NonNestedNamedRouteRouteWithChildren
   '/non-nested/path': typeof NonNestedPathRouteRouteWithChildren
@@ -838,6 +837,7 @@ export interface FileRoutesByTo {
   '/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute
   '/inside': typeof groupInsideRoute
   '/lazyinside': typeof groupLazyinsideRoute
+  '/pipe/$reference': typeof PipeReferenceRoute
   '/posts/$postId': typeof PostsPostIdRoute
   '/search-params/default': typeof SearchParamsDefaultRoute
   '/structural-sharing/$enabled': typeof StructuralSharingEnabledRoute
@@ -926,7 +926,6 @@ export interface FileRoutesById {
   '/notRemountDeps': typeof NotRemountDepsRoute
   '/posts': typeof PostsRouteWithChildren
   '/remountDeps': typeof RemountDepsRoute
-  '/special|pipe': typeof SpecialChar124pipeRoute
   '/non-nested/deep': typeof NonNestedDeepRouteRouteWithChildren
   '/non-nested/named': typeof NonNestedNamedRouteRouteWithChildren
   '/non-nested/path': typeof NonNestedPathRouteRouteWithChildren
@@ -941,6 +940,7 @@ export interface FileRoutesById {
   '/(group)/inside': typeof groupInsideRoute
   '/(group)/lazyinside': typeof groupLazyinsideRoute
   '/_layout/_layout-2': typeof LayoutLayout2RouteWithChildren
+  '/pipe/$reference': typeof PipeReferenceRoute
   '/posts/$postId': typeof PostsPostIdRoute
   '/redirect/$target': typeof RedirectTargetRouteWithChildren
   '/search-params/default': typeof SearchParamsDefaultRoute
@@ -1038,7 +1038,6 @@ export interface FileRouteTypes {
     | '/notRemountDeps'
     | '/posts'
     | '/remountDeps'
-    | '/special|pipe'
     | '/non-nested/deep'
     | '/non-nested/named'
     | '/non-nested/path'
@@ -1050,6 +1049,7 @@ export interface FileRouteTypes {
     | '/onlyrouteinside'
     | '/inside'
     | '/lazyinside'
+    | '/pipe/$reference'
     | '/posts/$postId'
     | '/redirect/$target'
     | '/search-params/default'
@@ -1143,7 +1143,6 @@ export interface FileRouteTypes {
     | '/masks'
     | '/notRemountDeps'
     | '/remountDeps'
-    | '/special|pipe'
     | '/non-nested/deep'
     | '/non-nested/named'
     | '/non-nested/path'
@@ -1155,6 +1154,7 @@ export interface FileRouteTypes {
     | '/onlyrouteinside'
     | '/inside'
     | '/lazyinside'
+    | '/pipe/$reference'
     | '/posts/$postId'
     | '/search-params/default'
     | '/structural-sharing/$enabled'
@@ -1242,7 +1242,6 @@ export interface FileRouteTypes {
     | '/notRemountDeps'
     | '/posts'
     | '/remountDeps'
-    | '/special|pipe'
     | '/non-nested/deep'
     | '/non-nested/named'
     | '/non-nested/path'
@@ -1257,6 +1256,7 @@ export interface FileRouteTypes {
     | '/(group)/inside'
     | '/(group)/lazyinside'
     | '/_layout/_layout-2'
+    | '/pipe/$reference'
     | '/posts/$postId'
     | '/redirect/$target'
     | '/search-params/default'
@@ -1354,7 +1354,6 @@ export interface RootRouteChildren {
   NotRemountDepsRoute: typeof NotRemountDepsRoute
   PostsRoute: typeof PostsRouteWithChildren
   RemountDepsRoute: typeof RemountDepsRoute
-  SpecialChar124pipeRoute: typeof SpecialChar124pipeRoute
   ParamsPsNonNestedRouteRoute: typeof ParamsPsNonNestedRouteRouteWithChildren
   RelativeLinkRouteRoute: typeof RelativeLinkRouteRouteWithChildren
   RelativeUseNavigateRouteRoute: typeof RelativeUseNavigateRouteRouteWithChildren
@@ -1362,6 +1361,7 @@ export interface RootRouteChildren {
   groupLayoutRoute: typeof groupLayoutRouteWithChildren
   groupInsideRoute: typeof groupInsideRoute
   groupLazyinsideRoute: typeof groupLazyinsideRoute
+  PipeReferenceRoute: typeof PipeReferenceRoute
   RedirectTargetRoute: typeof RedirectTargetRouteWithChildren
   StructuralSharingEnabledRoute: typeof StructuralSharingEnabledRoute
   ParamsPsIndexRoute: typeof ParamsPsIndexRoute
@@ -1387,13 +1387,6 @@ export interface RootRouteChildren {
 
 declare module '@tanstack/react-router' {
   interface FileRoutesByPath {
-    '/special|pipe': {
-      id: '/special|pipe'
-      path: '/special|pipe'
-      fullPath: '/special|pipe'
-      preLoaderRoute: typeof SpecialChar124pipeRouteImport
-      parentRoute: typeof rootRouteImport
-    }
     '/remountDeps': {
       id: '/remountDeps'
       path: '/remountDeps'
@@ -1562,6 +1555,13 @@ declare module '@tanstack/react-router' {
       preLoaderRoute: typeof PostsPostIdRouteImport
       parentRoute: typeof PostsRoute
     }
+    '/pipe/$reference': {
+      id: '/pipe/$reference'
+      path: '/pipe/$reference'
+      fullPath: '/pipe/$reference'
+      preLoaderRoute: typeof PipeReferenceRouteImport
+      parentRoute: typeof rootRouteImport
+    }
     '/_layout/_layout-2': {
       id: '/_layout/_layout-2'
       path: ''
@@ -2618,7 +2618,6 @@ const rootRouteChildren: RootRouteChildren = {
   NotRemountDepsRoute: NotRemountDepsRoute,
   PostsRoute: PostsRouteWithChildren,
   RemountDepsRoute: RemountDepsRoute,
-  SpecialChar124pipeRoute: SpecialChar124pipeRoute,
   ParamsPsNonNestedRouteRoute: ParamsPsNonNestedRouteRouteWithChildren,
   RelativeLinkRouteRoute: RelativeLinkRouteRouteWithChildren,
   RelativeUseNavigateRouteRoute: RelativeUseNavigateRouteRouteWithChildren,
@@ -2626,6 +2625,7 @@ const rootRouteChildren: RootRouteChildren = {
   groupLayoutRoute: groupLayoutRouteWithChildren,
   groupInsideRoute: groupInsideRoute,
   groupLazyinsideRoute: groupLazyinsideRoute,
+  PipeReferenceRoute: PipeReferenceRoute,
   RedirectTargetRoute: RedirectTargetRouteWithChildren,
   StructuralSharingEnabledRoute: StructuralSharingEnabledRoute,
   ParamsPsIndexRoute: ParamsPsIndexRoute,
diff --git a/e2e/react-router/basic-file-based/src/routes/__root.tsx b/e2e/react-router/basic-file-based/src/routes/__root.tsx
index dde8139a6e..ff04634fcb 100644
--- a/e2e/react-router/basic-file-based/src/routes/__root.tsx
+++ b/e2e/react-router/basic-file-based/src/routes/__root.tsx
@@ -156,6 +156,15 @@ function RootComponent() {
         >
           Masks
         </Link>{' '}
+        <Link
+          to="/pipe/$reference"
+          params={{ reference: 'hello|world' }}
+          activeProps={{
+            className: 'font-bold',
+          }}
+        >
+          Dynamic Pipe Character
+        </Link>{' '}
         <Link
           to="/pathless-layout"
           data-testid="link-to-pathless-layout"
diff --git a/e2e/react-router/basic-file-based/src/routes/pipe.$reference.tsx b/e2e/react-router/basic-file-based/src/routes/pipe.$reference.tsx
new file mode 100644
index 0000000000..4efb4d5622
--- /dev/null
+++ b/e2e/react-router/basic-file-based/src/routes/pipe.$reference.tsx
@@ -0,0 +1,10 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/pipe/$reference')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  const params = Route.useParams()
+  return <h4>Hello {params.reference}!</h4>
+}
diff --git a/e2e/react-router/basic-file-based/src/routes/special|pipe.tsx b/e2e/react-router/basic-file-based/src/routes/special|pipe.tsx
deleted file mode 100644
index e8b6e4e567..0000000000
--- a/e2e/react-router/basic-file-based/src/routes/special|pipe.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { createFileRoute } from '@tanstack/react-router'
-
-export const Route = createFileRoute('/special|pipe')({
-  component: () => <div>Hello /special|pipe!</div>,
-})
diff --git a/e2e/react-router/basic-file-based/tests/app.spec.ts b/e2e/react-router/basic-file-based/tests/app.spec.ts
index 2f6d0ccb88..43f429ad2a 100644
--- a/e2e/react-router/basic-file-based/tests/app.spec.ts
+++ b/e2e/react-router/basic-file-based/tests/app.spec.ts
@@ -400,10 +400,10 @@ test.describe('Special characters in route paths', () => {
     page,
     baseURL,
   }) => {
-    await page.goto('/special|pipe')
+    await page.goto('/pipe/hello|world')
 
-    await expect(page.locator('body')).toContainText('Hello /special|pipe!')
+    await expect(page.locator('body')).toContainText('Hello hello|world!')
 
-    expect(page.url()).toBe(`${baseURL}/special%7Cpipe`)
+    expect(page.url()).toBe(`${baseURL}/pipe/hello%7Cworld`)
   })
 })

From 8a683d919e1c17122acd495101e3769372612932 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=9D=B4=EC=A2=85=EA=B2=BD?= <gyoung3063413@naver.com>
Date: Sat, 10 Jan 2026 14:43:52 +0900
Subject: [PATCH 5/5] fixup! fix: update cleanPath to replace pipe characters
 with encoded value

---
 packages/router-core/src/path.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/router-core/src/path.ts b/packages/router-core/src/path.ts
index 4243d52d82..7f382fa6bd 100644
--- a/packages/router-core/src/path.ts
+++ b/packages/router-core/src/path.ts
@@ -19,7 +19,7 @@ export function joinPaths(paths: Array<string | undefined>) {
   )
 }
 
-/** Remove repeated slashes from a path string. */
+/** Remove repeated slashes and replace | to %7C from a path string. */
 export function cleanPath(path: string) {
   // remove double slashes
   return path.replace(/\/{2,}/g, '/').replace(/\|/g, '%7C')
