Files
next.js/errors/empty-generate-static-params.mdx
T
Wyatt JohnsonandGitHub 3cd8a23446 feat(cache-components): require non-empty generateStaticParams for validation (#85135)
### 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

- Addresses discrepancy discovered with
https://github.com/vercel/next.js/discussions/84925.
- Fixes https://github.com/vercel/next.js/issues/84801
2025-10-20 18:22:42 -06:00

70 lines
2.7 KiB
Plaintext

---
title: Empty generateStaticParams with Cache Components
---
## Why This Error Occurred
You're using [Cache Components](https://nextjs.org/docs/beta/app/api-reference/config/next-config-js/cacheComponents) in your Next.js application, and one of your `generateStaticParams` functions returned an empty array, which causes a build error.
When Cache Components is enabled, Next.js performs build-time validation to ensure your routes can be properly prerendered without runtime dynamic access errors. If `generateStaticParams` returns an empty array, Next.js cannot validate that your route won't access dynamic values (like `await cookies()`, `await headers()`, or `await searchParams`) at runtime, which would cause errors.
This strict requirement ensures:
- Build-time validation catches potential runtime errors early
- All routes using Cache Components have at least one static variant to validate against
- You don't accidentally deploy routes that will fail at runtime
## Possible Ways to Fix It
### Option 1: Return at least one static param
Modify your `generateStaticParams` function to return at least one set of parameters. This is the most common fix and allows build-time validation to work properly.
```tsx filename="app/blog/[slug]/page.tsx"
// ❌ This will cause an error with Cache Components
export async function generateStaticParams() {
return [] // Empty array not allowed
}
// ✅ Return at least one param
export async function generateStaticParams() {
return [{ slug: 'hello-world' }, { slug: 'getting-started' }]
}
```
### Option 2: Use a placeholder param for validation
If you don't know the actual values at build time but still want Cache Components, you can return a placeholder param for build-time validation:
> This is not recommended and should only be used if you absolutely need to as it prevents build-time validation from working which will likely cause runtime errors.
```tsx filename="app/blog/[slug]/page.tsx"
export async function generateStaticParams() {
// Return a placeholder for build-time validation
// Real params will be generated at runtime via ISR
return [{ slug: '__placeholder__' }]
}
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
// Handle placeholder case
if (slug === '__placeholder__') {
notFound()
}
// Your actual page logic
const post = await getPost(slug)
return <div>{post.title}</div>
}
```
## Useful Links
- [Cache Components Documentation](https://nextjs.org/docs/beta/app/api-reference/config/next-config-js/cacheComponents)
- [generateStaticParams API Reference](https://nextjs.org/docs/app/api-reference/functions/generate-static-params)