nextjs - ✅(Solved) Fix PPR on canary breaks static rendered pages using generateStaticParams [2 pull requests, 3 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#84584Fetched 2026-04-08 02:18:58
View on GitHub
Comments
3
Participants
3
Timeline
17
Reactions
0
Timeline (top)
labeled ×4commented ×3referenced ×3cross-referenced ×2

Fix Action

Fixed

PR fix notes

PR #84594: Fix incorrect SSG classification for dynamic pages with generateStaticParams

Description (problem / solution / changelog)

Fixing a bug

  • Related issues linked using fixes #84584
  • Tests added - regression test in test/production/app-dir/static-rendering-with-connection/
  • Errors have helpful links (N/A for this fix)

What?

Fixes a bug where pages with generateStaticParams that use dynamic APIs (cookies(), headers(), connection()) were incorrectly marked as SSG (●) in the build output, when they should be marked as Dynamic (ƒ).

Why?

This was causing users to mistakenly believe their pages were statically generated when they were actually rendered dynamically at request time. This led to confusion about deployment behavior and performance characteristics, as reported in #84584.

The bug occurred because the dynamic detection check ran before individual routes were processed during the build. The check looked at the pattern route (e.g., /blog/[slug]) which was never actually rendered, causing it to incorrectly return false for hasRevalidateZero. When the actual routes were processed later (e.g., /blog/post-1), they correctly detected revalidate: 0, but by then the parent page had already been classified as SSG.

How?

Added a second check in packages/next/src/build/index.ts after processing all prerendered routes. If any routes have revalidate: 0 (indicating they're dynamic), the parent page classification is corrected from SSG to Dynamic.

The fix includes:

  • Post-processing logic to correct page classification when routes turn out to be dynamic
  • Regression test with snapshot validation of build output
  • Test covers both standard mode and cache components mode (PPR)

Fixes #84584

NAR-430

Changed files

  • packages/next/src/build/index.ts (modified, +11/-0)
  • test/production/app-dir/build-output-tree-view/build-output-tree-view.test.ts (modified, +70/-0)
  • test/production/app-dir/build-output-tree-view/fixtures/dynamic-generate-static-params/app/dynamic/[slug]/page.tsx (added, +16/-0)
  • test/production/app-dir/build-output-tree-view/fixtures/dynamic-generate-static-params/app/layout.tsx (added, +11/-0)

PR #85135: feat(cache-components): require non-empty generateStaticParams for validation

Description (problem / solution / changelog)

What?

This PR adds build-time validation that requires generateStaticParams to return at least one result when Cache Components (experimental cacheComponents feature) is enabled.

Why?

Previously, users could return an empty array ([]) from generateStaticParams to indicate a route should be treated statically without providing specific parameter values. This pattern has a critical issue with Cache Components:

The Problem:

  • With Cache Components enabled, accessing params is treated as a dynamic API usage
  • When generateStaticParams returns empty results, Next.js cannot perform build-time validation to detect if the route accesses other dynamic APIs (like await cookies(), await headers(), or await searchParams)
  • This means users could successfully build routes that would fail at runtime with dynamic API errors

The Solution:

  • By requiring at least one parameter value, we can execute the route during build time with real params
  • This allows us to validate that the route doesn't make additional dynamic API calls that would cause runtime failures
  • Build-time validation catches configuration errors early, before deployment

How?

  • Modified buildAppStaticPaths in packages/next/src/build/static-paths/app.ts to check if PPR is enabled and throw error when generateStaticParams returns empty array with Cache Components enabled
  • Added comprehensive error documentation at errors/empty-generate-static-params.mdx with migration options

Migration paths provided in error documentation:

  1. Return at least one real param (recommended)
  2. Use placeholder params (not recommended, bypasses validation)

The breaking change is acceptable because cacheComponents is still experimental and only available in canary releases.

Related

Changed files

  • errors/empty-generate-static-params.mdx (added, +69/-0)
  • packages/next/errors.json (modified, +2/-1)
  • packages/next/src/build/static-paths/app.test.ts (modified, +72/-28)
  • packages/next/src/build/static-paths/app.ts (modified, +15/-3)
  • packages/next/src/shared/lib/errors/empty-generate-static-params-error.ts (added, +13/-0)
  • packages/next/src/shared/lib/errors/missing-default-parallel-route-error.ts (modified, +5/-7)
  • packages/next/src/shared/lib/errors/usage-error.ts (added, +10/-0)
  • test/e2e/app-dir/app-alias/src/app/typing/[slug]/page.tsx (modified, +1/-1)
  • test/e2e/app-dir/app-catch-all-optional/app/[lang]/[flags]/[[...rest]]/page.tsx (modified, +1/-1)
  • test/e2e/app-dir/not-found-with-pages-i18n/app/app-dir/[[...slug]]/page.tsx (modified, +1/-1)
  • test/e2e/app-dir/sub-shell-generation-middleware/app/rewrite/[slug]/page.tsx (modified, +1/-1)
  • test/e2e/app-dir/sub-shell-generation/app/[lang]/[slug]/page.tsx (modified, +1/-1)
  • test/production/app-dir/empty-generate-static-params/empty-generate-static-params.test.ts (modified, +33/-17)
  • test/production/standalone-mode/required-server-files/app/optional-catchall/[lang]/[flags]/[[...slug]]/page.jsx (modified, +1/-1)

Code Example

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 11 Home
  Available memory (MB): 16088
  Available CPU cores: 16
Binaries:
  Node: 23.11.0
  npm: 10.9.2
  Yarn: N/A
  pnpm: 10.18.0
Relevant Packages:
  next: 15.6.0-canary.47 // Latest available version is detected (15.6.0-canary.47).
  eslint-config-next: 15.5.4
  react: 19.2.0
  react-dom: 19.2.0
  typescript: 5.9.3
Next.js Config:
  output: N/A
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/juliansommer/workout-track

To Reproduce

Run pnpm build, you can see /exercises/[exercise] and /exercises/p/[page] are being server rendered on demand despite using generateStaticParams. ISSUE ONLY HAPPENS WITH PPR ON, tested on canary 47 with PPR off. During build it says "Generating static pages (983/983)" but then in the actual output says server rendered. Same issue when using --webpack in build, not turbopack specific. I tried putting "export const dynamic = "force-static" on the 2 routes and that just caused build errors.

Compare main branch on repo (canary with PPR on) to stable branch (canary with PPR off)

Current vs. Expected behavior

Should be like this image, with the routes being static <img width="997" height="878" alt="Image" src="https://github.com/user-attachments/assets/355415fa-1b21-471a-b671-5dc4d0832b99" />

Instead is like this when PPR is enabled, despite it not being enabled on those routes (adding experimental_ppr = false didnt change it either) <img width="977" height="832" alt="Image" src="https://github.com/user-attachments/assets/91f606cf-8da6-451b-b386-27f4d647725f" />

Provide environment information

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 11 Home
  Available memory (MB): 16088
  Available CPU cores: 16
Binaries:
  Node: 23.11.0
  npm: 10.9.2
  Yarn: N/A
  pnpm: 10.18.0
Relevant Packages:
  next: 15.6.0-canary.47 // Latest available version is detected (15.6.0-canary.47).
  eslint-config-next: 15.5.4
  react: 19.2.0
  react-dom: 19.2.0
  typescript: 5.9.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Partial Prerendering (PPR), Output, Turbopack, Webpack

Which stage(s) are affected? (Select all that apply)

next build (local), Vercel (Deployed)

Additional context

I tested on canary 30, canary 43, now same issue on latest (47)

extent analysis

TL;DR

The issue can be addressed by investigating the configuration of Partial Prerendering (PPR) in Next.js, specifically how it interacts with generateStaticParams and the dynamic export.

Guidance

  • Review the Next.js documentation on Partial Prerendering (PPR) to ensure it's correctly configured, especially considering the generateStaticParams method and its impact on static page generation.
  • Verify that the experimental_ppr option is correctly set to false for the affected routes, as the issue persists despite this setting.
  • Check the differences in configuration between the main branch (with PPR on) and the stable branch (with PPR off) to identify any discrepancies that might be causing the issue.
  • Consider testing with a minimal reproduction case to isolate the issue from other potential factors in the project.

Example

No specific code example can be provided without further details, but reviewing the next.config.js file for PPR settings and ensuring that generateStaticParams is correctly implemented for the affected routes is a good starting point.

Notes

The issue seems to be highly specific to the interaction between Next.js, PPR, and the project's configuration. Without more details on the project's setup and the exact configurations used, providing a precise solution is challenging.

Recommendation

Apply a workaround by carefully reviewing and adjusting the PPR configuration and generateStaticParams implementation to ensure they align with the expected static page generation behavior, as the root cause seems to be related to these aspects.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING