fix: resolve revalidate from cacheControl for null (notFound) page values - #233
Open
aevarOrigo wants to merge 1 commit into
Open
fix: resolve revalidate from cacheControl for null (notFound) page values#233aevarOrigo wants to merge 1 commit into
aevarOrigo wants to merge 1 commit into
Conversation
…lues getStaticProps/getServerSideProps returning `notFound: true` has no page content to cache, so Next.js's pages-router response cache calls CacheHandler#set() with `incrementalCacheValue` set to `null` (no `kind` property). resolveRevalidateValue() only read `ctx.cacheControl.revalidate` when the value's `kind` was "APP_PAGE" or "PAGES", so null values fell through to the unpopulated `ctx.revalidate` and silently defaulted to `defaultStaleAge` (1 year) regardless of the `revalidate` the page actually returned alongside `notFound: true`. Read ctx.cacheControl.revalidate for null/undefined values too, since that's exactly where the intended revalidate time already lives.
Collaborator
|
This PR conflicts with #232. |
AyronK
requested changes
Aug 6, 2026
| // `ctx.cacheControl.revalidate` in that case, so read it here too instead of | ||
| // silently falling through to the unpopulated `ctx.revalidate` below and | ||
| // defaulting to `defaultStaleAge`. | ||
| cachedPageValue == null |
Collaborator
There was a problem hiding this comment.
I don't agree that cachedPageValue == null is the right call here, it's not even === comparison.
If anything I'd go with return revalidate ?? responseCacheCtx.cacheControl?.revalidate ?? ctx.revalidate;
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
resolveRevalidateValue()only readsctx.cacheControl.revalidatewhen the cached value'skindis"APP_PAGE"or"PAGES". But when a Pages RoutergetStaticProps/getServerSidePropsreturnsnotFound: true, there's no page content to cache, so Next.js's response cache callsCacheHandler#set()withincrementalCacheValueset tonull— it has nokindat all.That means the
else ifnever matches fornotFound: trueresponses,revalidatefalls through toctx.revalidate, which the pages-router response cache never actually populates (response-cache/index.jsonly ever passes{ cacheControl, isRoutePPREnabled, isFallback }intoincrementalCache.set()), and the entry silently getsdefaultStaleAgeinstead of therevalidatevalue the page actually returned alongsidenotFound: true.Repro
kind: "PAGES"→ctx.cacheControl.revalidate(30) is read correctly.notFound: truepath: cached value isnull→ falls through toctx.revalidate(undefined) →defaultStaleAgeis used instead of10, regardless of what the page returned.With the default
defaultStaleAgeof31536000(1 year), everynotFound: trueresponse ends up with a ~1 year stale age in the underlying store no matter whatrevalidatethe page specifies.Fix
Also read
ctx.cacheControl.revalidatewhen the incremental cache value isnull/undefined, since that's exactly where the intended revalidate time already lives fornotFound: trueresponses.Test plan
resolveRevalidateValue.test.tscoveringFETCH,APP_PAGE,PAGES,null(the fix),undefined, unknownkind, and the no-value/no-ctx fallback cases.pnpm testinpackages/nextjs-cache-handler— all 34 tests pass.pnpm build(tsup --dts-resolve) — builds cleanly, no type errors.Happy to adjust the approach if you'd prefer handling this differently (e.g. inside
CacheHandler#set()instead ofresolveRevalidateValue()).