---
title: "Stop Next.js 16 Crashes: Fixing `searchParams` Errors"
slug: "stop-nextjs-16-from-crashing-on-searchparams"
published: "2025-11-09"
updated: "2025-11-12"
validated: "2025-11-12"
categories:
  - "Next.js"
tags:
  - "Next.js 15"
  - "searchParams"
  - "TypeError"
  - "Normalize searchParams"
  - "Next.js"
  - "React 19"
  - "Admin List Pagination"
  - "Vercel Error Fix"
llm-intent: "reference"
audience-level: "intermediate"
framework-versions:
  - "next.js@15"
  - "react@19"
  - "typescript@5"
  - "turbopack@latest"
  - "vercel@latest"
status: "stable"
llm-purpose: "Stop Next.js 16 from crashing due to `searchParams` errors. Learn effective techniques to handle type issues and ensure stability. Read now!"
llm-prereqs:
  - "Access to Next.js"
  - "Access to React"
  - "Access to Vercel"
  - "Access to TypeScript"
llm-outputs:
  - "Completed outcome: Stop Next.js 15 from crashing due to `searchParams` errors. Learn effective techniques to handle type issues and ensure stability. Read now!"
---

**Summary Triples**
- (Root cause, is, Next.js 15 server components receive ReadonlyURLSearchParams; missing keys become undefined so indexing like params.foo[0] throws a TypeError)
- (Fix, is, Normalize searchParams to accept ReadonlyURLSearchParams, URLSearchParams, Record<string,string|string[]|undefined>, null or undefined)
- (Implementation location, is, Create a helper in src/lib/utils.ts and use it everywhere you read query values in server components)
- (Helper behavior, must, Return the first string value or undefined, correctly handling arrays and URLSearchParams methods)
- (Outcome, prevents, cold-start runtime crashes on Vercel caused by direct indexing into searchParams)

### {GOAL}
Stop Next.js 16 from crashing due to `searchParams` errors. Learn effective techniques to handle type issues and ensure stability. Read now!

### {PREREQS}
- Access to Next.js
- Access to React
- Access to Vercel
- Access to TypeScript

### {STEPS}
1. Reproduce the Failure
2. Add Normalization Helper
3. Update Server Components
4. Redeploy and Validate

<!-- llm:goal="Stop Next.js 16 from crashing due to `searchParams` errors. Learn effective techniques to handle type issues and ensure stability. Read now!" -->
<!-- llm:prereq="Access to Next.js" -->
<!-- llm:prereq="Access to React" -->
<!-- llm:prereq="Access to Vercel" -->
<!-- llm:prereq="Access to TypeScript" -->
<!-- llm:output="Completed outcome: Stop Next.js 15 from crashing due to `searchParams` errors. Learn effective techniques to handle type issues and ensure stability. Read now!" -->

# Stop Next.js 16 Crashes: Fixing `searchParams` Errors
> Stop Next.js 16 from crashing due to `searchParams` errors. Learn effective techniques to handle type issues and ensure stability. Read now!
Matija Žiberna · 2025-11-09

I was working on a Next.js 16 project, happily paging through admin lists, when Vercel started screaming: “TypeError: Cannot read properties of undefined (reading '0')” right inside `.next/server/app/(admin)/admin/dobavnice/page.js`. React 19 and Turbopack already switched `searchParams` from the old plain object into a `ReadonlyURLSearchParams`, so every `params.foo?.[0]` in my server components fell apart at runtime. This guide shows how to normalize the new shape once, reuse it everywhere, and stop the cold-start crashes on Vercel.

## Step 1: Reproduce the failure and understand the new shape

Hit any page that still does `Array.isArray(params.foo)` on Next.js 15 and you’ll see the same stack trace:

```
TypeError: Cannot read properties of undefined (reading '0')
    at async m (.next/server/app/(admin)/admin/dobavnice/page.js:1:9228)
```

Server components now receive a promise that resolves to a `ReadonlyURLSearchParams`. Missing keys return `undefined`, so `params.page[0]` blows up. The fix is to read search params through a helper that understands every shape Next has ever returned: plain records, URLSearchParams, or nothing at all.

## Step 2: Add a helper that normalizes `searchParams`

Create or update `src/lib/utils.ts` with a helper that unwraps the key cleanly.

```typescript
// File: src/lib/utils.ts
import type { ReadonlyURLSearchParams } from "next/navigation"
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

export type SearchParamsLike =
  | ReadonlyURLSearchParams
  | URLSearchParams
  | Record<string, string | string[] | undefined>
  | null
  | undefined

export const getSearchParamValues = (
  params: SearchParamsLike,
  key: string
): string[] => {
  if (!params) return []

  if (typeof (params as URLSearchParams).getAll === "function") {
    const values = (params as URLSearchParams).getAll(key)
    return values.filter((value): value is string => typeof value === "string")
  }

  const record = params as Record<string, string | string[] | undefined>
  const raw = record?.[key]

  if (Array.isArray(raw)) {
    return raw.filter((value): value is string => typeof value === "string")
  }

  return typeof raw === "string" ? [raw] : []
}

export const getSearchParamValue = (
  params: SearchParamsLike,
  key: string
): string | undefined => {
  const [value] = getSearchParamValues(params, key)
  return value
}
```

The helper checks for URLSearchParams compatibility (`getAll`), falls back to the legacy record shape, and returns an empty array for nullish input. `getSearchParamValue` mirrors the old “first element or nothing” behaviour without the brittle `[0]` access.

## Step 3: Update server components to use the helper

Replace the manual `Array.isArray` logic in affected pages. Example refactor:

```typescript
// File: src/app/(admin)/admin/dobavnice/page.tsx
type AdminDeliveryNotesListPageProps = Readonly<{
  searchParams: Promise<SearchParamsLike>;
}>;

export default async function AdminDeliveryNotesListPage({
  searchParams,
}: AdminDeliveryNotesListPageProps) {
  const params = await searchParams;

  const page = Number.parseInt(getSearchParamValue(params, "page") ?? "1", 10);
  const search = getSearchParamValue(params, "search") ?? "";
  const statusParam = getSearchParamValue(params, "status");
  const status = statusParam ? (statusParam as DeliveryNoteStatus) : undefined;
  // ...
}
```

The rendering stays identical. Swap in the helper, update the prop type to `Promise<SearchParamsLike>`, and keep the business logic untouched. Repeat for other pages that previously relied on `Array.isArray(params.foo)`.

## Step 4: Redeploy and keep your build green

Run `pnpm build` (or `NEXT_DISABLE_TURBOPACK=1 pnpm next build`) locally to make sure the helper compiles. Redeploy to Vercel and the TypeError disappears because the runtime no longer dereferences `[0]` on `undefined`. Pagination and filters work exactly as before, only now they’re resilient to future Next.js changes.

## Wrap-up

Next.js 15 and React 19 changed the shape of `searchParams`, and the helper is the difference between healthy admin lists and Vercel’s “Cannot read properties of undefined” panic. By centralising the normalization and reusing it across your server components, you keep pagination, filters, and driver dashboards safe from the breaking change—all without rewriting your business logic.

Let me know in the comments if you have questions, and subscribe for more practical development guides.

Thanks, Matija

## LLM Response Snippet
```json
{
  "goal": "Stop Next.js 16 from crashing due to `searchParams` errors. Learn effective techniques to handle type issues and ensure stability. Read now!",
  "responses": [
    {
      "question": "What does the article \"Stop Next.js 15 Crashes: Fixing `searchParams` Errors\" cover?",
      "answer": "Stop Next.js 15 from crashing due to `searchParams` errors. Learn effective techniques to handle type issues and ensure stability. Read now!"
    }
  ]
}
```