Skip to content

Instant validation for caches excluded from prerenders - #98342

Open
lubieowoce wants to merge 3 commits into
lubieowoce/short-stale-is-not-runtimefrom
lubieowoce/instant-validation-excluded-caches
Open

Instant validation for caches excluded from prerenders#98342
lubieowoce wants to merge 3 commits into
lubieowoce/short-stale-is-not-runtimefrom
lubieowoce/instant-validation-excluded-caches

Conversation

@lubieowoce

@lubieowoce lubieowoce commented Sep 8, 2026

Copy link
Copy Markdown
Member

Follow-up to #98339. Turns out we were not testing how caches excluded from static/runtime prerenders and app shells behave in Instant Validation, and it was somewhat broken. This PR adds test coverage and fixes some bugs I found along the way.

Fixes

  • use-cache-wrapper was incorrectly gating cache delays in "request" stores on NODE_ENV === "development", which does not include build-time instant validation. The correct check is now implemented in isValidationRender
  • use-cache-wrapper has divergent behavior for caches with stale < MIN_SHELL_STALE across app shells and PPR/static shells, which needs to be tracked so that we know that the same render can't be used for both Instant and Static Shell validation. When we see a cache entry like that, we now call trackIncompatibleShellContent()
  • A render that had a cache miss could still report that it's compatible with both SSV and IV, because we only do the above for a cache hit. As a result so we'd incorrectly reuse LAZY_FULL_RENDER for both. Cache misses now result in a trackIncompatibleShellContent() call to avoid this

Tests

We now have tests for:

  • stale < MIN_SHELL_STALE - excluded from app shells, but included in static and runtime prefetches
  • stale < MIN_PREFETCHABLE_STALE - excluded from all prerenders
  • expire < MIN_PRERENDERABLE_EXPIRE - excluded from static prerenders, but allowed in runtime prerenders

Due to bugs mentioned above, some of the added tests were failing before the fixes (mostly the ones that expect an error -- passing a "no validation errors" test is easy, just don't create any dynamic holes)

In build, these tests incorrectly reported no errors when they should've failed IV:

  • invalid - unguarded non-prefetchable cache (with short stale) (both PPF and non-PPF)
  • non-app shell validation > invalid - unguarded non-prerenderable cache with short expire in build:
  • app shell validation > invalid - unguarded cache with a shorter-than-shell staleTime in build:

This is because we were missing cache delays in build-time instant validation (now fixed with isValidationRender), so the caches weren't dynamic holes at all.

The stale < MIN_SHELL_STALE tests (app shell validation > invalid - unguarded cache with a shorter-than-shell staleTime) were also failing in dev:

  • {initial load, client navigation} with cold caches: Should be an IV error, but is an SSV error. The initial render had cache misses, so we did a warm-cache full rerender with runtime shells, which resolved await nonShellCache() in the Runtime stage. But the initial render did not track incompatible data, so we incorrectly re-used it for SSV and IV. The cache was resolved in Runtime so SSV saw a runtime hole and await nonShellCache() errored in SSV with Next.js encountered runtime data during prerendering.
  • client navigation with warm caches: same as above, except there weren't cache misses, so incorrectly reused the original runtime-shell render for SSV and IV
  • initial load with warm caches: No redbox when IV should've errored. The main render was an initial load and did not use runtime shells, so it resolved await nonShellCache() in PrefetchStatic. We had no cache misses and did not track incompatible data, so we incorrectly re-used the main non-runtime-shell render for SSV and IV. The cache resolved in PrefetchStatic and it wasn't a hole in ShellRuntime so no error was reported.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Failing CI jobs

Commit: a29a48f | About building and testing Next.js

@lubieowoce
lubieowoce force-pushed the lubieowoce/instant-validation-excluded-caches branch 2 times, most recently from 7370b52 to 332b4d9 Compare September 8, 2026 04:48
@lubieowoce lubieowoce changed the title Instant validation for excluded caches Instant validation for caches excluded from prerenders Sep 8, 2026
@lubieowoce
lubieowoce marked this pull request as ready for review September 8, 2026 04:53
@lubieowoce
lubieowoce force-pushed the lubieowoce/instant-validation-excluded-caches branch from 332b4d9 to 8bdee62 Compare September 8, 2026 11:34
This also includes fixes around `RequestStore.hasIncompatibleShellContent`,
which would be `false` if the render had a cache miss for a cache
with `stale < MIN_SHELL_STALE`. We only track this when the cache is a
hit and we know its cache life, so misses would hide it.
@lubieowoce
lubieowoce force-pushed the lubieowoce/instant-validation-excluded-caches branch from 8bdee62 to a29a48f Compare September 8, 2026 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants