Repository: TanStack/router (2025-07-10T02:23:20Z)

Issue:
[Start] Pages with non-Latin characters in the route path are not rendered in TanStack Start
### Which project does this relate to?

Start

### Describe the bug

I’m building a project in Persian, which is a non-English language that uses a non-Latin alphabet. Today I noticed that pages with non-Latin characters in their route paths — like the example below:

```tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/تست')({
  component: RouteComponent,
})

function RouteComponent() {
  return <div>Hello "/تست"!</div>
}

```
are not being rendered.

And in the browser console, only this code/message is shown:

```html
<html><head></head><body></body></html>
```

### Your Example Website or App

https://github.com/Mrahmani71/test-tanstack-start

### Steps to Reproduce the Bug or Issue

After installing the packages and running the project, go to the following link — you’ll see that the page doesn’t render.

[http://localhost:3000/%D8%AA%D8%B3%D8%AA](http://localhost:3000/تست)

### Expected behavior

I expected this page to render just like other pages with Latin characters and display its content correctly.

### Screenshots or Videos

_No response_

### Platform

- Start Version: 1.125.6
- OS: Windows
- Browser: Brave 
- Browser Version: 1.80.120 / Chromium: 138.0.7204.101
- Bundler: Vite
- Bundler Version: 6.3.5


### Additional context

I didn’t have this issue with tanstack-router — the page was displayed correctly.


Discussion:
I can confirm this seems to be an issue. I am unsure how to solve
I'll take care of the issue and resolve it!



Patch:
diff --git a/packages/start-server-core/src/createStartHandler.ts b/packages/start-server-core/src/createStartHandler.ts
index dcfe9e7d4f8..0321412f924 100644
--- a/packages/start-server-core/src/createStartHandler.ts
+++ b/packages/start-server-core/src/createStartHandler.ts
@@ -110,7 +110,7 @@ export function createStartHandler<TRouter extends AnyRouter>({
       }
 
       const url = new URL(request.url)
-      const href = url.href.replace(url.origin, '')
+      const href = decodeURIComponent(url.href.replace(url.origin, ''))
 
       const APP_BASE = process.env.TSS_APP_BASE || '/'
 


Test patch:
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 4efc03e2827..8150c3354d4 100644
--- a/e2e/react-router/basic-file-based/src/routeTree.gen.ts
+++ b/e2e/react-router/basic-file-based/src/routeTree.gen.ts
@@ -11,6 +11,7 @@
 import { createFileRoute } from '@tanstack/react-router'
 
 import { Route as rootRouteImport } from './routes/__root'
+import { Route as Char45824Char54620Char48124Char44397RouteImport } from './routes/대한민국'
 import { Route as PostsRouteImport } from './routes/posts'
 import { Route as EditingBRouteImport } from './routes/editing-b'
 import { Route as EditingARouteImport } from './routes/editing-a'
@@ -58,6 +59,12 @@ const groupRoute = groupRouteImport.update({
   id: '/(group)',
   getParentRoute: () => rootRouteImport,
 } as any)
+const Char45824Char54620Char48124Char44397Route =
+  Char45824Char54620Char48124Char44397RouteImport.update({
+    id: '/대한민국',
+    path: '/대한민국',
+    getParentRoute: () => rootRouteImport,
+  } as any)
 const PostsRoute = PostsRouteImport.update({
   id: '/posts',
   path: '/posts',
@@ -272,6 +279,7 @@ export interface FileRoutesByFullPath {
   '/editing-a': typeof EditingARoute
   '/editing-b': typeof EditingBRoute
   '/posts': typeof PostsRouteWithChildren
+  '/대한민국': typeof Char45824Char54620Char48124Char44397Route
   '/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute
   '/inside': typeof groupInsideRoute
   '/lazyinside': typeof groupLazyinsideRoute
@@ -309,6 +317,7 @@ export interface FileRoutesByTo {
   '/anchor': typeof AnchorRoute
   '/editing-a': typeof EditingARoute
   '/editing-b': typeof EditingBRoute
+  '/대한민국': typeof Char45824Char54620Char48124Char44397Route
   '/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute
   '/inside': typeof groupInsideRoute
   '/lazyinside': typeof groupLazyinsideRoute
@@ -349,6 +358,7 @@ export interface FileRoutesById {
   '/editing-a': typeof EditingARoute
   '/editing-b': typeof EditingBRoute
   '/posts': typeof PostsRouteWithChildren
+  '/대한민국': typeof Char45824Char54620Char48124Char44397Route
   '/(another-group)/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute
   '/(group)': typeof groupRouteWithChildren
   '/(group)/_layout': typeof groupLayoutRouteWithChildren
@@ -393,6 +403,7 @@ export interface FileRouteTypes {
     | '/editing-a'
     | '/editing-b'
     | '/posts'
+    | '/대한민국'
     | '/onlyrouteinside'
     | '/inside'
     | '/lazyinside'
@@ -430,6 +441,7 @@ export interface FileRouteTypes {
     | '/anchor'
     | '/editing-a'
     | '/editing-b'
+    | '/대한민국'
     | '/onlyrouteinside'
     | '/inside'
     | '/lazyinside'
@@ -469,6 +481,7 @@ export interface FileRouteTypes {
     | '/editing-a'
     | '/editing-b'
     | '/posts'
+    | '/대한민국'
     | '/(another-group)/onlyrouteinside'
     | '/(group)'
     | '/(group)/_layout'
@@ -513,6 +526,7 @@ export interface RootRouteChildren {
   EditingARoute: typeof EditingARoute
   EditingBRoute: typeof EditingBRoute
   PostsRoute: typeof PostsRouteWithChildren
+  Char45824Char54620Char48124Char44397Route: typeof Char45824Char54620Char48124Char44397Route
   anotherGroupOnlyrouteinsideRoute: typeof anotherGroupOnlyrouteinsideRoute
   groupRoute: typeof groupRouteWithChildren
   RedirectTargetRoute: typeof RedirectTargetRouteWithChildren
@@ -543,6 +557,13 @@ declare module '@tanstack/react-router' {
       preLoaderRoute: typeof groupRouteImport
       parentRoute: typeof rootRouteImport
     }
+    '/대한민국': {
+      id: '/대한민국'
+      path: '/대한민국'
+      fullPath: '/대한민국'
+      preLoaderRoute: typeof Char45824Char54620Char48124Char44397RouteImport
+      parentRoute: typeof rootRouteImport
+    }
     '/posts': {
       id: '/posts'
       path: '/posts'
@@ -928,6 +949,8 @@ const rootRouteChildren: RootRouteChildren = {
   EditingARoute: EditingARoute,
   EditingBRoute: EditingBRoute,
   PostsRoute: PostsRouteWithChildren,
+  Char45824Char54620Char48124Char44397Route:
+    Char45824Char54620Char48124Char44397Route,
   anotherGroupOnlyrouteinsideRoute: anotherGroupOnlyrouteinsideRoute,
   groupRoute: groupRouteWithChildren,
   RedirectTargetRoute: RedirectTargetRouteWithChildren,
diff --git "a/e2e/react-router/basic-file-based/src/routes/\353\214\200\355\225\234\353\257\274\352\265\255.tsx" "b/e2e/react-router/basic-file-based/src/routes/\353\214\200\355\225\234\353\257\274\352\265\255.tsx"
new file mode 100644
index 00000000000..c70cb5096a9
--- /dev/null
+++ "b/e2e/react-router/basic-file-based/src/routes/\353\214\200\355\225\234\353\257\274\352\265\255.tsx"
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/대한민국')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/대한민국"!</div>
+}
diff --git a/e2e/react-router/basic-file-based/tests/params.spec.ts b/e2e/react-router/basic-file-based/tests/params.spec.ts
index 5d4c6111b78..546fa80d31e 100644
--- a/e2e/react-router/basic-file-based/tests/params.spec.ts
+++ b/e2e/react-router/basic-file-based/tests/params.spec.ts
@@ -202,3 +202,13 @@ test.describe('params operations + prefix/suffix', () => {
     })
   })
 })
+
+test.describe('Unicode route rendering', () => {
+  test('should render non-latin route correctly', async ({ page, baseURL }) => {
+    await page.goto('/대한민국')
+
+    await expect(page.locator('body')).toContainText('Hello "/대한민국"!')
+
+    expect(page.url()).toBe(`${baseURL}/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD`)
+  })
+})
diff --git a/e2e/react-start/basic/src/routeTree.gen.ts b/e2e/react-start/basic/src/routeTree.gen.ts
index 1eaa3c34e22..b6fc9282f67 100644
--- a/e2e/react-start/basic/src/routeTree.gen.ts
+++ b/e2e/react-start/basic/src/routeTree.gen.ts
@@ -17,6 +17,7 @@ import type {
 import { createServerRootRoute } from '@tanstack/react-start/server'
 
 import { Route as rootRouteImport } from './routes/__root'
+import { Route as Char45824Char54620Char48124Char44397RouteImport } from './routes/대한민국'
 import { Route as UsersRouteImport } from './routes/users'
 import { Route as StreamRouteImport } from './routes/stream'
 import { Route as ScriptsRouteImport } from './routes/scripts'
@@ -58,6 +59,12 @@ import { ServerRoute as ApiUsersIdServerRouteImport } from './routes/api/users.$
 const FooBarQuxRouteImport = createFileRoute('/foo/$bar/$qux')()
 const rootServerRouteImport = createServerRootRoute()
 
+const Char45824Char54620Char48124Char44397Route =
+  Char45824Char54620Char48124Char44397RouteImport.update({
+    id: '/대한민국',
+    path: '/대한민국',
+    getParentRoute: () => rootRouteImport,
+  } as any)
 const UsersRoute = UsersRouteImport.update({
   id: '/users',
   path: '/users',
@@ -262,6 +269,7 @@ export interface FileRoutesByFullPath {
   '/scripts': typeof ScriptsRoute
   '/stream': typeof StreamRoute
   '/users': typeof UsersRouteWithChildren
+  '/대한민국': typeof Char45824Char54620Char48124Char44397Route
   '/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
   '/not-found/via-loader': typeof NotFoundViaLoaderRoute
   '/posts/$postId': typeof PostsPostIdRoute
@@ -293,6 +301,7 @@ export interface FileRoutesByTo {
   '/links': typeof LinksRoute
   '/scripts': typeof ScriptsRoute
   '/stream': typeof StreamRoute
+  '/대한민국': typeof Char45824Char54620Char48124Char44397Route
   '/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
   '/not-found/via-loader': typeof NotFoundViaLoaderRoute
   '/posts/$postId': typeof PostsPostIdRoute
@@ -328,6 +337,7 @@ export interface FileRoutesById {
   '/scripts': typeof ScriptsRoute
   '/stream': typeof StreamRoute
   '/users': typeof UsersRouteWithChildren
+  '/대한민국': typeof Char45824Char54620Char48124Char44397Route
   '/_layout/_layout-2': typeof LayoutLayout2RouteWithChildren
   '/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
   '/not-found/via-loader': typeof NotFoundViaLoaderRoute
@@ -367,6 +377,7 @@ export interface FileRouteTypes {
     | '/scripts'
     | '/stream'
     | '/users'
+    | '/대한민국'
     | '/not-found/via-beforeLoad'
     | '/not-found/via-loader'
     | '/posts/$postId'
@@ -398,6 +409,7 @@ export interface FileRouteTypes {
     | '/links'
     | '/scripts'
     | '/stream'
+    | '/대한민국'
     | '/not-found/via-beforeLoad'
     | '/not-found/via-loader'
     | '/posts/$postId'
@@ -432,6 +444,7 @@ export interface FileRouteTypes {
     | '/scripts'
     | '/stream'
     | '/users'
+    | '/대한민국'
     | '/_layout/_layout-2'
     | '/not-found/via-beforeLoad'
     | '/not-found/via-loader'
@@ -471,6 +484,7 @@ export interface RootRouteChildren {
   ScriptsRoute: typeof ScriptsRoute
   StreamRoute: typeof StreamRoute
   UsersRoute: typeof UsersRouteWithChildren
+  Char45824Char54620Char48124Char44397Route: typeof Char45824Char54620Char48124Char44397Route
   RedirectTargetRoute: typeof RedirectTargetRouteWithChildren
   RedirectIndexRoute: typeof RedirectIndexRoute
   PostsPostIdDeepRoute: typeof PostsPostIdDeepRoute
@@ -573,6 +587,13 @@ declare module '@tanstack/react-router' {
       preLoaderRoute: typeof UsersRouteImport
       parentRoute: typeof rootRouteImport
     }
+    '/대한민국': {
+      id: '/대한민국'
+      path: '/대한민국'
+      fullPath: '/대한민국'
+      preLoaderRoute: typeof Char45824Char54620Char48124Char44397RouteImport
+      parentRoute: typeof rootRouteImport
+    }
     '/_layout/_layout-2': {
       id: '/_layout/_layout-2'
       path: ''
@@ -843,6 +864,13 @@ declare module '@tanstack/react-start/server' {
       preLoaderRoute: unknown
       parentRoute: typeof rootServerRouteImport
     }
+    '/대한민국': {
+      id: '/대한민국'
+      path: '/대한민국'
+      fullPath: '/대한민국'
+      preLoaderRoute: unknown
+      parentRoute: typeof rootServerRouteImport
+    }
     '/_layout/_layout-2': {
       id: '/_layout/_layout-2'
       path: ''
@@ -1205,6 +1233,23 @@ declare module './routes/users' {
     unknown
   >
 }
+declare module './routes/대한민국' {
+  const createFileRoute: CreateFileRoute<
+    '/대한민국',
+    FileRoutesByPath['/대한민국']['parentRoute'],
+    FileRoutesByPath['/대한민국']['id'],
+    FileRoutesByPath['/대한민국']['path'],
+    FileRoutesByPath['/대한민국']['fullPath']
+  >
+
+  const createServerFileRoute: CreateServerFileRoute<
+    ServerFileRoutesByPath['/대한민국']['parentRoute'],
+    ServerFileRoutesByPath['/대한민국']['id'],
+    ServerFileRoutesByPath['/대한민국']['path'],
+    ServerFileRoutesByPath['/대한민국']['fullPath'],
+    unknown
+  >
+}
 declare module './routes/_layout/_layout-2' {
   const createFileRoute: CreateFileRoute<
     '/_layout/_layout-2',
@@ -1818,6 +1863,8 @@ const rootRouteChildren: RootRouteChildren = {
   ScriptsRoute: ScriptsRoute,
   StreamRoute: StreamRoute,
   UsersRoute: UsersRouteWithChildren,
+  Char45824Char54620Char48124Char44397Route:
+    Char45824Char54620Char48124Char44397Route,
   RedirectTargetRoute: RedirectTargetRouteWithChildren,
   RedirectIndexRoute: RedirectIndexRoute,
   PostsPostIdDeepRoute: PostsPostIdDeepRoute,
diff --git "a/e2e/react-start/basic/src/routes/\353\214\200\355\225\234\353\257\274\352\265\255.tsx" "b/e2e/react-start/basic/src/routes/\353\214\200\355\225\234\353\257\274\352\265\255.tsx"
new file mode 100644
index 00000000000..99448326772
--- /dev/null
+++ "b/e2e/react-start/basic/src/routes/\353\214\200\355\225\234\353\257\274\352\265\255.tsx"
@@ -0,0 +1,7 @@
+export const Route = createFileRoute({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/대한민국"!</div>
+}
diff --git a/e2e/react-start/basic/tests/params.spec.ts b/e2e/react-start/basic/tests/params.spec.ts
new file mode 100644
index 00000000000..b22c3e26554
--- /dev/null
+++ b/e2e/react-start/basic/tests/params.spec.ts
@@ -0,0 +1,15 @@
+import { expect, test } from '@playwright/test'
+
+test.beforeEach(async ({ page }) => {
+  await page.goto('/')
+})
+
+test.describe('Unicode route rendering', () => {
+  test('should render non-latin route correctly', async ({ page, baseURL }) => {
+    await page.goto('/대한민국')
+
+    await expect(page.locator('body')).toContainText('Hello "/대한민국"!')
+
+    expect(page.url()).toBe(`${baseURL}/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD`)
+  })
+})