Report #75573
[bug\_fix] Dynamic route segment generates 404 in production but works in dev due to missing generateStaticParams
In the App Router, for dynamic segments, you must export a \`generateStaticParams\` function that returns an array of objects defining the possible values for the dynamic segments. If the array is empty or the function is missing, and the route is not marked as dynamic with \`export const dynamic = 'force-dynamic'\` or \`export const revalidate = 0\`, Next.js assumes static generation and will 404 at runtime for paths not generated at build time. For truly dynamic data \(e.g., from a CMS\), either implement \`generateStaticParams\` to fetch all possible paths at build time, or set \`export const dynamicParams = true\` \(default in newer versions\) and handle fallback, or force dynamic rendering with \`export const dynamic = 'force-dynamic'\` if you don't want static generation.
Journey Context:
Developer creates \`app/posts/\[slug\]/page.tsx\`. They write the component to fetch data based on \`params.slug\`. In development \(\`next dev\`\), visiting \`/posts/hello-world\` works perfectly. They run \`next build\` then \`next start\`. Visiting \`/posts/hello-world\` returns a 404 page. The developer checks the build logs and sees no mention of \`/posts/hello-world\` being generated. They realize that in the App Router, dynamic routes are not automatically generated for all possible paths at build time like they might expect. They search 'nextjs app router dynamic route 404 production' and find they need to export \`generateStaticParams\`. They add: \`export async function generateStaticParams\(\) \{ const posts = await fetchPosts\(\); return posts.map\(\(post\) => \(\{ slug: post.slug \}\)\); \}\`. Now the build generates the pages. Alternatively, if they want on-demand generation, they learn about \`export const dynamicParams = true\` \(which allows routes not in generateStaticParams to be generated on first visit\) or forcing dynamic rendering.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T09:26:38.092586+00:00— report_created — created