vercel/next.js · error · StaticGenBailoutError

Route ${store.route} with `dynamic = "error"` couldn't be re

Error message

Route ${store.route} with `dynamic = "error"` couldn't be rendered statically because it used `${expression}`. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering

What it means

A StaticGenBailoutError from markCurrentScopeAsDynamic(). When a route is configured with dynamic = 'error' (or dynamicParams = false in some contexts) and the render attempts to use a dynamic API (the `expression`, e.g. cookies(), headers(), searchParams, or reading request data), the framework refuses to render it statically. dynamicShouldError is true, so instead of postponing, it throws this bailout error.

Source

Thrown at packages/next/src/server/app-render/dynamic-rendering.ts:205

        // A private cache scope is already dynamic by definition.
        return
      case 'prerender-legacy':
      case 'prerender-ppr':
      case 'request':
      case 'generate-static-params':
        break
      default:
        workUnitStore satisfies never
    }
  }

  // If we're forcing dynamic rendering or we're forcing static rendering, we
  // don't need to do anything here because the entire page is already dynamic
  // or it's static and it should not throw or postpone here.
  if (store.forceDynamic || store.forceStatic) return

  if (store.dynamicShouldError) {
    throw new StaticGenBailoutError(
      `Route ${store.route} with \`dynamic = "error"\` couldn't be rendered statically because it used \`${expression}\`. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`
    )
  }

  if (workUnitStore) {
    switch (workUnitStore.type) {
      case 'prerender-ppr':
        return postponeWithTracking(
          store.route,
          expression,
          workUnitStore.dynamicTracking
        )
      case 'prerender-legacy':
        workUnitStore.revalidate = 0

        // We aren't prerendering, but we are generating a static page. We need
        // to bail out of static generation.
        const err = new DynamicServerError(

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Remove or change `export const dynamic = 'error'` to 'force-static', 'force-dynamic', or omit it to allow the appropriate rendering mode.
  2. Move the dynamic API call (cookies/headers/searchParams) out of the static component into a component rendered dynamically, or into a Client Component.
  3. If the access is unintentional, audit the component (and imported shared components) for cookies()/headers()/searchParams usage and remove it.
  4. Use `export const dynamicParams = false` instead if you only want to restrict dynamic route params, not all dynamic data.

Example fix

// before
// export const dynamic = 'error'
// export default function Page({ cookies }) { const c = cookies() ... }

// after
// export const dynamic = 'force-dynamic'
// export default function Page() { const c = cookies() ... }
Defensive patterns

Strategy: type-guard

Validate before calling

// Static analysis: ensure dynamic APIs aren't used in static routes.
// At code level, decide rendering mode based on data needs:
const needsDynamic = (page) => page.usesCookies || page.usesHeaders
export const dynamic = needsDynamic(this) ? 'force-dynamic' : 'error'

Prevention

When it happens

Trigger: A page/layout sets `export const dynamic = 'error'` (meaning: this route MUST be static, error if it can't be). During prerender/static generation, the component calls a dynamic function (cookies(), headers(), searchParams, or uses request-only data). markCurrentScopeAsDynamic sees store.dynamicShouldError and throws StaticGenBailoutError.

Common situations: A developer adds `dynamic = 'error'` to force static rendering but the component reads cookies/headers/searchParams; a shared component unexpectedly calls a dynamic API; upgrading Next.js where stricter dynamic detection now flags a previously-allowed access; mixing dynamic data fetch with a static-only intent.

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/9432395079f3245e. Report an issue: GitHub.