static-viewport-dynamic.mdx


title: Next.js encountered uncached data in generateViewport() 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, generateViewport() performed an uncached fetch() request, database call, or connection(). The operation requires rendering at request time, which conflicts with the route's static requirement.

During next build, Next.js may link to this page when it cannot distinguish uncached data from runtime data. For a short cache, extend the cache lifetime.

Request-specific reads from cookies(), headers(), params, or searchParams have different fixes. See Runtime data in generateViewport() on a route that must be fully static.

Ways to fix this

<FixCardGrid> <FixCard group="cache" title="Cache the viewport" href="#cache-the-viewport" snippets={[ { text: 'async function generateViewport() {' }, { text: ' "use cache"', highlight: true }, { text: ' return await cms.getViewport(…)' }, ]} /> <FixCard group="static" title="Use static viewport" href="#use-static-viewport" snippets={[ { text: 'export const viewport = {', highlight: true }, { text: " themeColor: 'black'" }, { text: '}' }, ]} /> </FixCardGrid>

Cache the viewport

Choose this fix when viewport data can be shared across requests.

Patterns

Add use cache to generateViewport()

Cache generateViewport() with use cache and choose an appropriate cacheLife profile:

import { cacheLife } from 'next/cache'

export async function generateViewport() {
  'use cache'
  cacheLife('hours')
  const response = await fetch('https://api.example.com/content')
  const data = await response.json()
  return { themeColor: data.themeColor }
}

Learn more: Caching with use cache.

Trade-off

Visitors share the cached viewport data until it is revalidated.

Gotchas

  • This fix does not apply to connection(), whose purpose is to require request-time rendering.
  • Caching does not make cookies, headers, parameters, or search parameters static.

Use static viewport

Choose this fix when viewport settings do not need the uncached value.

Patterns

Export a static viewport object

Replace generateViewport() with a static viewport export:

export const viewport = { themeColor: 'black' }

Learn more: Static viewport.

Trade-off

The viewport is determined during prerendering rather than from the removed data source.

Gotchas

  • This fixes viewport settings only. Page content, metadata, and other segments must also satisfy the static requirement.
  • If the value must be generated for each request, first confirm that request-time rendering is intended for the entire route. See Remove the static requirement.

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 operation in Suspense or setting instant = false does not relax this static requirement.

In next dev, the error overlay points at the failing function 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 viewport settings.

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.

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.

errors/static-viewport-dynamic.mdx · vercel/next.js | Docs MD