static-route-runtime.mdx
title: Next.js encountered runtime data on a route that must be fully static kind: error
<div style={{ padding: '1.25rem 1.5rem', border: '1px solid var(--ds-gray-400)', borderRadius: '12px', background: 'var(--ds-background-200)', margin: '1.5rem 0 2rem', fontSize: '0.95rem', lineHeight: '1.6', }} > This error is part of the [Instant Navigations](https://nextjs.org/blog/next-16-3-instant-navigations) feature introduced in Next.js 16.3. If you're new to it, start with the [Ensuring instant navigations](/docs/app/guides/instant-navigation) guide. </div>A page or layout on this route exports ensureStatic with the 'navigation' value, requiring all server-rendered work for the route to complete during prerendering.
During prerendering, the page or layout read request-specific data from cookies(), headers(), params, or searchParams. Reading these values requires rendering at request time, which conflicts with the route's static requirement.
A use cache scope also triggers this error when its expire is under five minutes, stale is under 30 seconds, or revalidate is 0.
Uncached fetch() requests, database calls, and connection() have different fixes. See Uncached data on a route that must be fully static.
Ways to fix this
<FixCardGrid> <FixCard group="remove" title="Remove the data access" href="#remove-the-data-access" snippets={[ { text: 'async function Page() {' }, { text: '- const store = await cookies()', highlight: true }, { text: ' return <Content />' }, ]} /> <FixCard group="client" title="Read the data on the client" href="#read-the-data-on-the-client" snippets={[ { text: "'use client'" }, { text: 'use(browser())', highlight: true }, { text: 'const value = readBrowserData()' }, ]} /> </FixCardGrid>Remove the data access
Choose this fix when the content does not need to vary by request. Replace the request-specific value with a value available during prerendering.
Patterns
Remove the request-specific read
Remove the runtime API call and use a value that can be determined during prerendering.
export const ensureStatic = 'navigation'
export default function Page() {
return <h1>My page</h1>
}
Trade-off
Every visitor receives the same value because the route no longer reads request-specific data.
Gotchas
- This fix applies to
cookies(),headers(), and other removable reads. It does not provide replacement values when the content must vary by request.
Read the data on the client
Choose this fix when the browser can read the value and the server does not need it to produce static output.
Patterns
Read URL data in a Client Component
Use useSearchParams() for the query string or useParams() for route parameters. If the hook suspends during prerendering, render the Client Component inside Suspense so the prerender can include its fallback.
'use client'
import { useSearchParams } from 'next/navigation'
export default function Query() {
const searchParams = useSearchParams()
return <p>Query: {searchParams.get('q')}</p>
}
Learn more: useSearchParams.
Read browser data
For data available through browser APIs, such as a non-HttpOnly cookie, call use(browser()) before reading the value. During prerendering, the component suspends and its nearest <Suspense> boundary renders a fallback.
'use client'
import { use } from 'react'
import { browser } from 'react-dom'
export default function CartCount() {
use(browser('The cart count is stored in a cookie.'))
const match = document.cookie.match(/(?:^|; )cart-count=(\d+)/)
return <p>Cart ({Number(match?.[1] ?? 0)})</p>
}
Learn more: Rendering components only in the browser.
Trade-off
The prerender includes the nearest fallback. The request-specific UI appears after the browser loads and renders the Client Component.
Gotchas
- Adding
'use client'alone does not fix this error because Client Components are also prerendered. Use a client hook that suspends or calluse(browser())before reading a browser API. - Do not pass the server's
paramsorsearchParamspromise to the Client Component. Read URL data with the client hooks instead. - The browser cannot read
HttpOnlycookies or arbitrary request headers. Keep sensitive data inHttpOnlycookies and choose another fix when the browser cannot access the value safely.
Other options
Extend the cache lifetime
Set expire to at least five minutes, stale to at least 30 seconds, and revalidate above 0. Increase the lifetime only when serving shared, older content is acceptable.
Learn more: cacheLife.
Verifying the fix
After applying a fix, rerun next build and confirm that the route completes prerendering. If the error also appeared in next dev, reload the route and confirm that the overlay clears. Wrapping the access in Suspense or setting instant = false does not relax this static requirement.
In next dev, the error overlay points at the failing component with file paths and line numbers. Run next build --debug-prerender for full user-frame stack traces and next build --debug-build-paths /dashboard /settings to iterate on specific routes.
Remove the static requirement
The 'navigation' value is usually set deliberately to guarantee static output for the entire server-rendered route. Removing it relaxes that requirement for every segment, not only the code that triggered this error.
If request-time rendering is intentional for this route, remove ensureStatic = 'navigation' from every page or layout that sets it. The route then follows the ordinary Cache Components rendering rules.
Learn more: Combining ensureStatic levels across layouts and pages.
Related validation errors
See Instant Navigation validation errors for the complete reference.
Rendered from the public repository vercel/next.js on GitHub; content belongs to its authors. Cached for up to an hour.