
Fix “params should be awaited” in Next.js App Router
Fix the Next.js “params should be awaited” error in App Router pages and layouts, with safe TypeScript patterns and a migration checklist.
In Next.js 15 and later, dynamic route params are asynchronous. The direct code change is small, but pages, layouts, and metadata generators all need the correct Promise shape.
Resolve params at the server boundary
Make the page or layout async, await params once, then pass plain values to the rest of the application.
params.slugSync access fails in Next.js 15+const { slug } = await paramsResolve once at the server boundarytype PageProps = { params: Promise<{ slug: string }> }
export default async function Page({ params }: PageProps) {
const { slug } = await params
const post = await getPost(slug)
return <Article post={post} />
}Update generateMetadata too
Metadata often gets missed because it's not visible in the page UI. Await params before loading a title, description, canonical URL, or Open Graph data.
type Props = { params: Promise<{ slug: string }> }
export async function generateMetadata({ params }: Props) {
const { slug } = await params
return { title: (await getPost(slug)).title }
}Keep Client Components synchronous
Prefer resolving the Promise in a Server Component and passing plain data down. Use React’s use API only where a Promise genuinely must cross a client boundary.
Verify the whole route
rg "\b(params|searchParams)\b" app src
npm run lint
npm run buildTest a real dynamic route in a production build, including its metadata and 404 behavior. This catches the remaining synchronous access paths.
If the upgrade also left a page visually broken, use theNext.js CSS troubleshooting guideto isolate imports, modules, Tailwind output, and production assets.
Reproduce the example
npm run lint && npm run build
Sources and further reading
- Dynamic APIs are Asynchronous · Vercel
- Upgrading: Version 15 · Vercel
- Dynamic Routes · Vercel