Description
Link to the code that reproduces this issue
https://github.com/emilioestebanez/next-15-issues
To Reproduce
npm i
npm run build
npm run start
Go to http://localhost:3000/example-200 (which is a status 200 page) and check the Cache-Control headers --> you get s-maxage=20, stale-while-revalidate=31535980
Go to http://localhost:3000/missingpage (which is a status 404 page) and check the Cache-Control headers --> you get s-maxage=31536000,
Current vs. Expected behavior
When visiting a 404 page (e.g. http://localhost:3000/missingpage) I get Cache-Control = s-maxage=31536000,
I expect it to inherit the revalidate value from the page.tsx
(20 seconds in the example), and it shouldn't have this ,
at the end.
Provide environment information
Operating System:
Platform: win32
Arch: x64
Version: Windows 11 Pro
Available memory (MB): 65208
Available CPU cores: 20
Binaries:
Node: 22.12.0
npm: 10.9.0
Yarn: N/A
pnpm: 9.15.3
Relevant Packages:
next: 15.2.0-canary.8 // Latest available version is detected (15.2.0-canary.8).
eslint-config-next: 15.1.0
react: 19.0.0
react-dom: 19.0.0
typescript: 5.7.2
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Runtime
Which stage(s) are affected? (Select all that apply)
next start (local), Other (Deployed)
Additional context
This was closed in #74865 without taking into account this comment:
There is code in packages/next/src/server/base-server.ts
that tries to get the original revalidate time from the page that caused the 404 (I'm not sure if this is only for the pages router):
https://github.com/vercel/next.js/blob/canary/packages/next/src/server/base-server.ts#L3248
// If we are rendering the 404 page we derive the cache-control
// revalidate period from the value that trigged the not found
// to be rendered. So if `getStaticProps` returns
// { notFound: true, revalidate 60 } the revalidate period should
// be 60 but if a static asset 404s directly it should have a revalidate
// period of 0 so that it doesn't get cached unexpectedly by a CDN
else if (is404Page) {
const notFoundRevalidate = getRequestMeta(req, 'notFoundRevalidate')
revalidate =
typeof notFoundRevalidate === 'undefined' ? 0 : notFoundRevalidate
} else if (is500Page) {
revalidate = 0
}
In any case, even if you can't get the original revalidate value from the page, we should definitely not cache 404 responses for a year!
E.g. imagine you have a CMS, or an e-Commerce:
- You have a product in the URL
/my-product
. - Then, you unpublish your product from your e-Commerce, thus getting a 404 page in
/my-product
- A few days later, you want to publish the product again
- At this point, you need to wait for a year for the
/my-product
URL to be working again!