---
id: router.validated-search
kind: recipe
product: router
framework: react
locale: en
revision: 2
sourceCheckedOn: "2026-08-03"
versionRange: "^1"
verifiedAgainst: "@tanstack/react-router@1.170.18"
contentModel: 2
packages:
  - "@tanstack/react-router"
tasks:
  - "validate-search-params"
  - "pagination"
  - "url-state"
sourceRefs:
  - "https://tanstack.com/router/latest/docs/guide/search-params"
---

# Validate pagination and filter search params

> Turn untrusted URL search params into stable, typed route input.

## Execution contract

- **Use when:** Use for filters, sorting, pagination, or shareable view state owned by the URL.
- **Avoid when:** Do not store secrets, transient input, or large values that cannot be safely serialized.
- **Preconditions:** Define allowed keys, runtime validation, defaults, and the canonical serialized URL shape.
- **Verification:** Test valid, missing, and malformed values; refresh, back, and shared links must restore the same view.
- **Failure mode:** If an update clears other keys, verify the search updater merges from previous state instead of returning a partial object.
- **Security:** URL input is untrusted; successful parsing does not make it safe for SQL, file paths, or outbound requests.

## Contract

validateSearch receives parsed but untrusted values. Its return value becomes the search type seen by loaders, Route.useSearch(), and child routes.

## Implementation

Give invalid page values a stable default and constrain status to an explicit union.

File: `src/routes/issues/index.tsx`

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

export const Route = createFileRoute('/issues/')({
  validateSearch: (search: Record<string, unknown>) => ({
    page: Math.max(1, Number(search.page) || 1),
    status: search.status === 'closed' ? 'closed' as const : 'open' as const,
  }),
  component: IssuesPage,
})

function IssuesPage() {
  const { page, status } = Route.useSearch()
  return <p>{status} issues · page {page}</p>
}
```

## Common failures

Do not reparse search values in every component. Do not assume Number() yields a valid number. If the project already uses Zod or Valibot, reuse its existing schema.

## Official sources

- https://tanstack.com/router/latest/docs/guide/search-params
