nextjs runtime_error ai_generated true

Error: Route used `searchParams.X`. `searchParams` should be awaited before using its properties.

ID: nextjs/searchparams-sync-access

Also available as: JSON · Markdown
95%Fix Rate
95%Confidence
80Evidence
2024-10-01First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
14 active

Root Cause

Next.js 15 changed searchParams and params from synchronous objects to Promises. Code that accesses searchParams.X directly without awaiting will fail. This is a breaking change from Next.js 14.

generic

Workarounds

  1. 96% success Await searchParams before accessing its properties in Server Components
    // Next.js 15+ page.tsx
    export default async function Page({
      searchParams,
    }: {
      searchParams: Promise<{ q?: string }>
    }) {
      const params = await searchParams;
      const query = params.q;
      return <div>Search: {query}</div>;
    }

    Sources: https://nextjs.org/docs/app/api-reference/file-conventions/page#searchparams-optional https://nextjs.org/blog/next-15#async-request-apis-breaking-change

  2. 90% success Use React.use() to unwrap the searchParams promise in Client Components
    'use client';
    import { use } from 'react';
    
    export default function Page({
      searchParams,
    }: {
      searchParams: Promise<{ q?: string }>
    }) {
      const params = use(searchParams);
      return <div>Search: {params.q}</div>;
    }

    Sources: https://nextjs.org/blog/next-15#async-request-apis-breaking-change

  3. 92% success Use the next/headers cookies() and headers() with await as well during migration
    // Next.js 15: all request APIs are now async
    import { cookies, headers } from 'next/headers';
    
    export default async function Page({
      searchParams,
    }: {
      searchParams: Promise<{ q?: string }>
    }) {
      const [params, cookieStore, headerList] = await Promise.all([
        searchParams,
        cookies(),
        headers(),
      ]);
      // use params.q, cookieStore.get('token'), etc.
    }

    Sources: https://nextjs.org/blog/next-15#async-request-apis-breaking-change

Dead Ends

Common approaches that don't work:

  1. Downgrade to Next.js 14 to avoid the breaking change 70% fail

    Downgrading avoids the immediate error but locks the project out of Next.js 15 features and security updates. The migration is straightforward and should be done instead.

  2. Type searchParams as a plain object (e.g., { X: string }) without Promise 92% fail

    TypeScript types may suppress editor errors, but at runtime searchParams is still a Promise. Accessing properties without await returns undefined or throws.

  3. Use useSearchParams() hook in a Server Component to get synchronous access 88% fail

    useSearchParams() is a Client Component hook and cannot be used in Server Components. In Server Components, the only way to access search params is through the page/layout props which are now Promises.

Error Chain

Leads to:
Preceded by:
Frequently confused with: