It isn't possible to have an _error.tsx file in the /pages folder without also having a 404.tsx file. When running next dev, it works fine, but as soon as you run next build, the following error appears:
Automatically optimizing pages ...
Error occurred prerendering page "/404". Read more: https://err.sh/next.js/prerender-error:
Error: Error for page /_error: pages with `getServerSideProps` can not be exported. See more info here: https://err.sh/next.js/gss-export
According to the official Next.js Blog, it should not be a problem to have a _error.tsx without a 404.tsx: https://nextjs.org/blog/next-9-3#automatic-static-optimization-for-404
The reason I do not want a static 404 page is so that I can catch routes with a trailing slash and redirect accordingly to the route without a trailing slash. This must be done on the server.
Steps to reproduce the behavior, please provide code snippets or a repository:
_error.tsx file with a getServerSideProps() function.next build.The error message says that it is trying to export the _error.tsx file even though it obviously shouldn't be. The application should still build. As soon as I add a 404.tsx file or remove the _error.tsx file, it builds without a problem.
Just in case it might be of any use, here is the code from my _error.tsx file:
import React, { useEffect } from 'react';
import { GetServerSideProps } from 'next';
import Head from 'next/head';
import Router from 'next/router';
import { makeStyles, createStyles } from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';
import useStandardHeaderTags from '../lib/useStandardHeaderTags';
import TitleElement from '../components/TitleElement';
const useStyles = makeStyles(() =>
createStyles({
root: {
textAlign: 'center'
}
})
);
interface Props {
statusCode: number;
}
const Error: React.FC<Props> = ({ statusCode }) => {
const classes = useStyles();
const title = statusCode === 404 ? '404' : 'Error';
return (
<>
<Head>
{useStandardHeaderTags(title)}
</Head>
<Container className={classes.root}>
<TitleElement text={title} />
{statusCode === 404
? 'The page you are looking for could not be found.'
: 'An error occurred.'}
</Container>
</>
);
};
export const getServerSideProps: GetServerSideProps = async ({ res, req }) => {
const statusCode = res ? res.statusCode : 404;
if (statusCode === 404) {
if (req.url.match(/\/$/)) {
const withoutTrailingSlash = req.url.substr(0, req.url.length - 1);
if (res) {
res.writeHead(303, {
Location: withoutTrailingSlash
});
res.end();
}
else {
Router.push(withoutTrailingSlash);
}
}
}
return {
props: {
statusCode
}
};
};
export default Error;
Same as #12246
Replied here: https://github.com/zeit/next.js/discussions/11945#discussioncomment-6790
The reason I do not want a static 404 page is so that I can catch routes with a trailing slash and redirect accordingly to the route without a trailing slash. This must be done on the server.
What you're looking for seems to be https://github.com/zeit/next.js/issues/9081
pages/_error can't use getServerSideProps on purpose as explained in https://github.com/zeit/next.js/discussions/11945#discussioncomment-6790. pages/404.js can't use getServerSideProps on purpose too as it massively increases server load without a good reason, eg all 404 routes would server-render on-demand with the code that you wrote.
What we can do is improve the error message / documentation around it.
Thank you for the replies! What isn鈥檛 clear to me though is whether the redirects feature is already available in the latest version of Next.js as it was still marked as open. Also, is it possible to create a redirect with a regex-based src key so that I can redirect all routes with a trailing slash?
This issue is unfortunately holding up the launch our website...
I was, however, able to solve it by changing the getServierSideProps function to
Error.getInitialProps = ({ res, req, err }): Props => {
const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
if (statusCode === 404) {
if (req.url.match(/\/$/)) {
const withoutTrailingSlash = req.url.substr(0, req.url.length - 1);
if (res) {
res.writeHead(303, {
Location: withoutTrailingSlash
});
res.end();
}
else {
Router.push(withoutTrailingSlash);
}
}
}
return { statusCode };
};
That works well.
pages/_errorcan't use getServerSideProps on purpose as explained in https://github.com/zeit/next.js/discussions/11945#discussioncomment-6790.pages/404.jscan't usegetServerSidePropson purpose too as it massively increases server load without a good reason, eg all 404 routes would server-render on-demand with the code that you wrote.
Shouldn't be this up to the developer to decide? Feels like being too babysitted here. In our case we would like to serve different 404 pages depending on the language. Now I'm forced to use a useEffect inside the 404 page to trigger the language change, which shows a flash of the English version.
Has this possibly been fixed?
I've just tested next with just index.js, _app.js and _error.js and it worked without a 404.js.
nvm, this bug is still present.
When _error.js has getInitialProps a 404.js is not required, but otherwise it is
Most helpful comment
Shouldn't be this up to the developer to decide? Feels like being too babysitted here. In our case we would like to serve different 404 pages depending on the language. Now I'm forced to use a useEffect inside the 404 page to trigger the language change, which shows a flash of the English version.