-
Notifications
You must be signed in to change notification settings - Fork 30k
fix 500 custom _error rendering in minimal mode #86597
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| /** | ||
| * @type {import('next').NextConfig} | ||
| */ | ||
| const nextConfig = {} | ||
|
|
||
| module.exports = nextConfig |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import { nextTestSetup } from 'e2e-utils' | ||
|
|
||
| describe('pages-get-initial-props-error', () => { | ||
| const { next } = nextTestSetup({ | ||
| files: __dirname, | ||
| }) | ||
|
|
||
| it('should render _error with 500 status code when getInitialProps throws', async () => { | ||
| const browser = await next.browser('/gip-error') | ||
| expect(await browser.elementByCss('p').text()).toBe( | ||
| 'An error 500 occurred on server' | ||
| ) | ||
|
|
||
| const response = await next.fetch('/gip-error') | ||
| expect(response.status).toBe(500) | ||
| }) | ||
| }) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| import type { AppProps } from 'next/app' | ||
|
|
||
| export default function App({ Component, pageProps }: AppProps) { | ||
| return <Component {...pageProps} /> | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import { Html, Head, Main, NextScript } from 'next/document' | ||
|
|
||
| export default function Document() { | ||
| return ( | ||
| <Html> | ||
| <Head /> | ||
| <body> | ||
| <Main /> | ||
| <NextScript /> | ||
| </body> | ||
| </Html> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| import type { NextPageContext } from 'next' | ||
|
|
||
| type ErrorProps = { | ||
| statusCode?: number | ||
| } | ||
|
|
||
| function ErrorPage({ statusCode }: ErrorProps) { | ||
| return ( | ||
| <p> | ||
| {statusCode !== undefined | ||
| ? `An error ${statusCode} occurred on server` | ||
| : 'An error occurred on client'} | ||
| </p> | ||
| ) | ||
| } | ||
|
|
||
| ErrorPage.getInitialProps = ({ res, err }: NextPageContext) => { | ||
| console.log('ErrorPage.gip:err', err, '!!res', !!res) | ||
| let statusCode = 200 | ||
| try { | ||
| statusCode = res?.statusCode ?? err?.statusCode ?? (res || err ? 500 : 404) | ||
| } catch (error) { | ||
| console.error('ErrorPage.gip:try-catch', error) | ||
| } | ||
|
|
||
| console.trace( | ||
| 'ErrorPage.status code', | ||
| 'res?.statusCode', | ||
| res?.statusCode, | ||
| 'err?.statusCode', | ||
| err?.statusCode, | ||
| 'final', | ||
| statusCode | ||
| ) | ||
| return { statusCode } | ||
| } | ||
|
|
||
| export default ErrorPage |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import type { GetServerSideProps } from 'next' | ||
|
|
||
| class IntentionalServerError extends Error { | ||
| statusCode: number | ||
|
|
||
| constructor(message: string, statusCode = 500) { | ||
| super(message) | ||
| this.name = 'IntentionalServerError' | ||
| this.statusCode = statusCode | ||
| } | ||
| } | ||
|
|
||
| export default function ErrorDemo() { | ||
| return <h1>Custom Error Page Demo</h1> | ||
| } | ||
|
|
||
| export const getServerSideProps: GetServerSideProps = async () => { | ||
| throw new IntentionalServerError( | ||
| 'Intentional error triggered via getServerSideProps.' | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1060,7 +1060,10 @@ describe('required server files', () => { | |
| it('should bubble error correctly for gip page', async () => { | ||
| const res = await fetchViaHTTP(appPort, '/errors/gip', { crash: '1' }) | ||
| expect(res.status).toBe(500) | ||
| expect(await res.text()).toBe('Internal Server Error') | ||
| const body = await res.text() | ||
| const $ = cheerio.load(body) | ||
| expect($('h1').text()).toBe('500') | ||
| expect($('h2').text()).toBe('Internal Server Error.') | ||
|
|
||
| await retry(() => { | ||
| expect(errors.join('\n')).toInclude('gip hit an oops') | ||
|
|
@@ -1070,7 +1073,10 @@ describe('required server files', () => { | |
| it('should bubble error correctly for gssp page', async () => { | ||
| const res = await fetchViaHTTP(appPort, '/errors/gssp', { crash: '1' }) | ||
| expect(res.status).toBe(500) | ||
| expect(await res.text()).toBe('Internal Server Error') | ||
| const body = await res.text() | ||
| const $ = cheerio.load(body) | ||
| expect($('h1').text()).toBe('500') | ||
| expect($('h2').text()).toBe('Internal Server Error.') | ||
|
|
||
| await retry(() => { | ||
| expect(errors.join('\n')).toInclude('gssp hit an oops') | ||
|
|
@@ -1080,7 +1086,10 @@ describe('required server files', () => { | |
| it('should bubble error correctly for gsp page', async () => { | ||
| const res = await fetchViaHTTP(appPort, '/errors/gsp/crash') | ||
| expect(res.status).toBe(500) | ||
| expect(await res.text()).toBe('Internal Server Error') | ||
| const body = await res.text() | ||
| const $ = cheerio.load(body) | ||
| expect($('h1').text()).toBe('500') | ||
| expect($('h2').text()).toBe('Internal Server Error.') | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels off, when we are in minimal mode we don't actually return the rendered content we only invoke |
||
|
|
||
| await retry(() => { | ||
| expect(errors.join('\n')).toInclude('gsp hit an oops') | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.