Skip to content

Commit c0d3d68

Browse files
committed
fix pages handler _error
1 parent e0008a9 commit c0d3d68

File tree

8 files changed

+107
-8
lines changed

8 files changed

+107
-8
lines changed

packages/next/src/server/route-modules/pages/pages-handler.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -691,11 +691,10 @@ export const getHandler = ({
691691
}
692692

693693
// when invoking _error before pages/500 we don't actually
694-
// send the _error response
695-
if (
696-
getRequestMeta(req, 'customErrorRender') ||
697-
(isErrorPage && isMinimalMode && res.statusCode === 500)
698-
) {
694+
// send the _error response - only skip if customErrorRender is set
695+
// (meaning pages/500 exists and will be rendered next), or if using
696+
// the builtin _error in minimalMode to allow error bubbling
697+
if (getRequestMeta(req, 'customErrorRender')) {
699698
return null
700699
}
701700

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/**
2+
* @type {import('next').NextConfig}
3+
*/
4+
const nextConfig = {}
5+
6+
module.exports = nextConfig
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { nextTestSetup } from 'e2e-utils'
2+
3+
describe('pages-get-initial-props-error', () => {
4+
const { next } = nextTestSetup({
5+
files: __dirname,
6+
})
7+
8+
it('should render _error with 500 status code when getInitialProps throws', async () => {
9+
const browser = await next.browser('/gip-error')
10+
expect(await browser.elementByCss('p').text()).toBe(
11+
'An error 500 occurred on server'
12+
)
13+
14+
const response = await next.fetch('/gip-error')
15+
expect(response.status).toBe(500)
16+
})
17+
})
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import type { AppProps } from 'next/app'
2+
3+
export default function App({ Component, pageProps }: AppProps) {
4+
return <Component {...pageProps} />
5+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Html, Head, Main, NextScript } from 'next/document'
2+
3+
export default function Document() {
4+
return (
5+
<Html>
6+
<Head />
7+
<body>
8+
<Main />
9+
<NextScript />
10+
</body>
11+
</Html>
12+
)
13+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { NextPageContext } from 'next'
2+
3+
type ErrorProps = {
4+
statusCode?: number
5+
}
6+
7+
function ErrorPage({ statusCode }: ErrorProps) {
8+
return (
9+
<p>
10+
{statusCode !== undefined
11+
? `An error ${statusCode} occurred on server`
12+
: 'An error occurred on client'}
13+
</p>
14+
)
15+
}
16+
17+
ErrorPage.getInitialProps = ({ res, err }: NextPageContext) => {
18+
console.log('ErrorPage.gip:err', err, '!!res', !!res)
19+
let statusCode = 200
20+
try {
21+
statusCode = res?.statusCode ?? err?.statusCode ?? (res || err ? 500 : 404)
22+
} catch (error) {
23+
console.error('ErrorPage.gip:try-catch', error)
24+
}
25+
26+
console.trace(
27+
'ErrorPage.status code',
28+
'res?.statusCode',
29+
res?.statusCode,
30+
'err?.statusCode',
31+
err?.statusCode,
32+
'final',
33+
statusCode
34+
)
35+
return { statusCode }
36+
}
37+
38+
export default ErrorPage
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import type { GetServerSideProps } from 'next'
2+
3+
class IntentionalServerError extends Error {
4+
statusCode: number
5+
6+
constructor(message: string, statusCode = 500) {
7+
super(message)
8+
this.name = 'IntentionalServerError'
9+
this.statusCode = statusCode
10+
}
11+
}
12+
13+
export default function ErrorDemo() {
14+
return <h1>Custom Error Page Demo</h1>
15+
}
16+
17+
export const getServerSideProps: GetServerSideProps = async () => {
18+
throw new IntentionalServerError(
19+
'Intentional error triggered via getServerSideProps.'
20+
)
21+
}

test/production/required-server-files-ssr-404/test/index.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -551,19 +551,19 @@ describe('Required Server Files', () => {
551551
it('should bubble error correctly for gip page', async () => {
552552
const res = await fetchViaHTTP(appPort, '/errors/gip', { crash: '1' })
553553
expect(res.status).toBe(500)
554-
expect(await res.text()).toBe('Internal Server Error')
554+
expect(await res.text()).toContain('500 - Internal Server Error.')
555555
})
556556

557557
it('should bubble error correctly for gssp page', async () => {
558558
const res = await fetchViaHTTP(appPort, '/errors/gssp', { crash: '1' })
559559
expect(res.status).toBe(500)
560-
expect(await res.text()).toBe('Internal Server Error')
560+
expect(await res.text()).toContain('500 - Internal Server Error.')
561561
})
562562

563563
it('should bubble error correctly for gsp page', async () => {
564564
const res = await fetchViaHTTP(appPort, '/errors/gsp/crash')
565565
expect(res.status).toBe(500)
566-
expect(await res.text()).toBe('Internal Server Error')
566+
expect(await res.text()).toContain('500 - Internal Server Error.')
567567
})
568568

569569
it('should normalize optional values correctly for SSP page', async () => {

0 commit comments

Comments
 (0)