diff --git a/packages/next/server/base-server.ts b/packages/next/server/base-server.ts index b12de614bffff..f4d3187d3f157 100644 --- a/packages/next/server/base-server.ts +++ b/packages/next/server/base-server.ts @@ -22,6 +22,7 @@ import { NormalizeError, DecodeError, normalizeRepeatedSlashes, + MissingStaticPage, } from '../shared/lib/utils' import type { PreviewData } from 'next/types' import type { PagesManifest } from '../build/webpack/plugins/pages-manifest-plugin' @@ -1856,6 +1857,26 @@ export default abstract class Server { } } catch (error) { const err = getProperError(error) + + if (error instanceof MissingStaticPage) { + console.error( + 'Invariant: failed to load static page', + JSON.stringify( + { + page, + url: ctx.req.url, + matchedPath: ctx.req.headers['x-matched-path'], + initUrl: getRequestMeta(ctx.req, '__NEXT_INIT_URL'), + didRewrite: getRequestMeta(ctx.req, '_nextDidRewrite'), + rewroteUrl: getRequestMeta(ctx.req, '_nextRewroteUrl'), + }, + null, + 2 + ) + ) + throw err + } + if (err instanceof NoFallbackError && bubbleNoFallback) { throw err } diff --git a/packages/next/server/require.ts b/packages/next/server/require.ts index aeb7de6224523..e6cb5a0302640 100644 --- a/packages/next/server/require.ts +++ b/packages/next/server/require.ts @@ -11,7 +11,7 @@ import { normalizeLocalePath } from '../shared/lib/i18n/normalize-locale-path' import { normalizePagePath } from '../shared/lib/page-path/normalize-page-path' import { denormalizePagePath } from '../shared/lib/page-path/denormalize-page-path' import type { PagesManifest } from '../build/webpack/plugins/pages-manifest-plugin' -import { PageNotFoundError } from '../shared/lib/utils' +import { PageNotFoundError, MissingStaticPage } from '../shared/lib/utils' export function getPagePath( page: string, @@ -90,7 +90,9 @@ export function requirePage( appDirEnabled ) if (pagePath.endsWith('.html')) { - return promises.readFile(pagePath, 'utf8') + return promises.readFile(pagePath, 'utf8').catch((err) => { + throw new MissingStaticPage(page, err.message) + }) } return require(pagePath) } diff --git a/packages/next/shared/lib/utils.ts b/packages/next/shared/lib/utils.ts index c541f81bff60b..321f52b618986 100644 --- a/packages/next/shared/lib/utils.ts +++ b/packages/next/shared/lib/utils.ts @@ -413,6 +413,13 @@ export class PageNotFoundError extends Error { } } +export class MissingStaticPage extends Error { + constructor(page: string, message: string) { + super() + this.message = `Failed to load static file for page: ${page} ${message}` + } +} + export class MiddlewareNotFoundError extends Error { code: string constructor() { diff --git a/test/production/required-server-files.test.ts b/test/production/required-server-files.test.ts index 42ef827ceafd5..b376f71065677 100644 --- a/test/production/required-server-files.test.ts +++ b/test/production/required-server-files.test.ts @@ -138,6 +138,24 @@ describe('should set-up next', () => { if (server) await killApp(server) }) + it('should show invariant when an automatic static page is requested', async () => { + const toRename = `standalone/.next/server/pages/auto-static.html` + await next.renameFile(toRename, `${toRename}.bak`) + + try { + const res = await fetchViaHTTP(appPort, '/auto-static', undefined, { + headers: { + 'x-matched-path': '/auto-static', + }, + }) + + expect(res.status).toBe(500) + await check(() => stderr, /Invariant: failed to load static page/) + } finally { + await next.renameFile(`${toRename}.bak`, toRename) + } + }) + it.each([ { case: 'redirect no revalidate', diff --git a/test/production/required-server-files/pages/auto-static.js b/test/production/required-server-files/pages/auto-static.js new file mode 100644 index 0000000000000..a015d4120d6cc --- /dev/null +++ b/test/production/required-server-files/pages/auto-static.js @@ -0,0 +1,3 @@ +export default function Page() { + return

automatic static page

+}