Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Throw an error for empty array return in generateStaticParams with output:export #57053

Merged
merged 9 commits into from
Jan 4, 2024
22 changes: 13 additions & 9 deletions packages/next/src/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1708,15 +1708,19 @@ export default async function build(
const isDynamic = isDynamicRoute(page)
const hasGenerateStaticParams =
!!workerResult.prerenderRoutes?.length

if (
config.output === 'export' &&
isDynamic &&
!hasGenerateStaticParams
) {
throw new Error(
`Page "${page}" is missing "generateStaticParams()" so it cannot be used with "output: export" config.`
)
const isEmptyGenerateStaticParams =
workerResult.prerenderRoutes?.length === 0

if (config.output === 'export' && isDynamic) {
if (isEmptyGenerateStaticParams) {
throw new Error(
`Page "${page}"'s "generateStaticParams()" returned an empty array, which is not allowed with "output: export" config.`
)
} else if (!hasGenerateStaticParams) {
throw new Error(
`Page "${page}" is missing "generateStaticParams()" so it cannot be used with "output: export" config.`
)
}
}

if (
Expand Down
7 changes: 6 additions & 1 deletion packages/next/src/server/base-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1794,7 +1794,12 @@ export default abstract class Server<ServerOptions extends Options = Options> {
)
}
const resolvedWithoutSlash = removeTrailingSlash(resolvedUrlPathname)
if (!staticPaths?.includes(resolvedWithoutSlash)) {
if (!staticPaths || staticPaths.length === 0) {
throw new Error(
`Page "${page}"'s "generateStaticParams()" returned an empty array, which is not allowed with "output: export" config.`
)
}
if (!staticPaths.includes(resolvedWithoutSlash)) {
throw new Error(
`Page "${page}" is missing param "${resolvedWithoutSlash}" in "generateStaticParams()", which is required with "output: export" config.`
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,15 @@ describe('app dir - with output export - dynamic missing gsp dev', () => {
'Page "/another/[slug]/page" cannot use both "use client" and export function "generateStaticParams()".',
})
})

it('should error when generateStaticParams returns an empty array', async () => {
await runTests({
isDev: true,
dynamicPage: 'undefined',
generateStaticParamsOpt: 'set empty',
expectedErrMsg:
'Page "/another/[slug]/page"\'s "generateStaticParams()" returned an empty array, which is not allowed with "output: export" config.',
})
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,15 @@ describe('app dir - with output export - dynamic missing gsp prod', () => {
'Page "/another/[slug]/page" cannot use both "use client" and export function "generateStaticParams()".',
})
})

it('should error when generateStaticParams returns an empty array', async () => {
await runTests({
isDev: false,
dynamicPage: 'undefined',
generateStaticParamsOpt: 'set empty',
expectedErrMsg:
'Page "/another/[slug]"\'s "generateStaticParams()" returned an empty array, which is not allowed with "output: export" config.',
})
})
})
})
7 changes: 6 additions & 1 deletion test/integration/app-dir-export/test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export async function runTests({
trailingSlash?: boolean
dynamicPage?: string
dynamicApiRoute?: string
generateStaticParamsOpt?: 'set noop' | 'set client'
generateStaticParamsOpt?: 'set noop' | 'set client' | 'set empty'
expectedErrMsg?: string
}) {
if (trailingSlash !== undefined) {
Expand All @@ -124,6 +124,11 @@ export async function runTests({
slugPage.replace('export function generateStaticParams', 'function noop')
} else if (generateStaticParamsOpt === 'set client') {
slugPage.prepend('"use client"\n')
} else if (generateStaticParamsOpt === 'set empty') {
slugPage.replace(
"return [{ slug: 'first' }, { slug: 'second' }]",
'return []'
)
}
await fs.remove(distDir)
await fs.remove(exportDir)
Expand Down