Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 39dd0f5

Browse files
authored
Correct statusCode when visiting _error directly (vercel#26610)
This fixes non-stop reloading when visiting `_error` directly in development caused by the `statusCode` being 200 unexpectedly while HMR returns the page as `invalid` which triggers `on-demand-entries` to reload the page. ## Bug - [x] Related issues linked using `fixes #number` - [x] Integration tests added Fixes: vercel#8036 x-ref: vercel#8033
1 parent 93dc35f commit 39dd0f5

File tree

2 files changed

+22
-37
lines changed

2 files changed

+22
-37
lines changed

packages/next/next-server/server/next-server.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,6 +1444,7 @@ export default class Server {
14441444
): Promise<string | null> {
14451445
const is404Page = pathname === '/404'
14461446
const is500Page = pathname === '/500'
1447+
const isErrorPage = pathname === '/_error'
14471448

14481449
const isLikeServerless =
14491450
typeof components.Component === 'object' &&
@@ -1462,6 +1463,10 @@ export default class Server {
14621463
res.statusCode = 404
14631464
}
14641465

1466+
if (isErrorPage && res.statusCode === 200) {
1467+
res.statusCode = 404
1468+
}
1469+
14651470
// ensure correct status is set when visiting a status page
14661471
// directly e.g. /500
14671472
if (STATIC_STATUS_PAGES.includes(pathname)) {

test/integration/client-navigation/test/index.test.js

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,46 +25,26 @@ describe('Client Navigation', () => {
2525
context.server = await launchApp(join(__dirname, '../'), context.appPort, {
2626
env: { __NEXT_TEST_WITH_DEVTOOL: 1 },
2727
})
28-
29-
const prerender = [
30-
'/async-props',
31-
'/default-head',
32-
'/empty-get-initial-props',
33-
'/error',
34-
'/finish-response',
35-
'/head',
36-
'/json',
37-
'/link',
38-
'/stateless',
39-
'/fragment-syntax',
40-
'/custom-extension',
41-
'/styled-jsx',
42-
'/styled-jsx-external',
43-
'/with-cdm',
44-
'/url-prop',
45-
46-
'/dynamic/ssr',
47-
'/dynamic/[slug]/route',
48-
49-
'/nav',
50-
'/nav/about',
51-
'/nav/on-click',
52-
'/nav/querystring',
53-
'/nav/self-reload',
54-
'/nav/hash-changes',
55-
'/nav/shallow-routing',
56-
'/nav/redirect',
57-
'/nav/as-path',
58-
'/nav/as-path-using-router',
59-
60-
'/nested-cdm',
61-
]
62-
await Promise.all(
63-
prerender.map((route) => renderViaHTTP(context.appPort, route))
64-
)
6528
})
6629
afterAll(() => killApp(context.server))
6730

31+
it('should not reload when visiting /_error directly', async () => {
32+
const browser = await webdriver(context.appPort, '/_error')
33+
34+
await browser.eval('window.hello = true')
35+
36+
// wait on-demand-entries timeout since it can trigger
37+
// reloading non-stop
38+
for (let i = 0; i < 15; i++) {
39+
expect(await browser.eval('window.hello')).toBe(true)
40+
await waitFor(1000)
41+
}
42+
const html = await browser.eval('document.documentElement.innerHTML')
43+
44+
expect(html).toContain('This page could not be found')
45+
expect(html).toContain('404')
46+
})
47+
6848
describe('with <Link/>', () => {
6949
it('should navigate the page', async () => {
7050
const browser = await webdriver(context.appPort, '/nav')

0 commit comments

Comments
 (0)