mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 08:25:34 +02:00
[GH-ISSUE #921] revalidatePath() does not invalidate fetches in nested routes (missing layout implicit tags) #204
Labels
No labels
enhancement
enhancement
good first issue
help wanted
nextjs-tracking
nextjs-tracking
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/vinext#204
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @james-elicx on GitHub (Apr 27, 2026).
Original GitHub issue: https://github.com/cloudflare/vinext/issues/921
Summary
revalidatePath('/parent')does not invalidate cachedfetch()results rendered inside child routes (e.g./parent/child). After #917 lands,revalidatePath()invalidates fetches rendered at the exact path, but the layout-chain case is still broken.Background
#917 added route-scoped implicit tags as soft tags on App Router fetch reads. The generated entry calls:
The second argument is the layout-segment list, hardcoded to
[]at every call site. As a result, the only soft tag a render carries is the page-level path tag (_N_T_/parent/child).Next.js derives a chain of layout tags in addition to the page tag — see
getImplicitTags. For/parent/child, Next.js attaches roughly:_N_T_/layout(root)_N_T_/parent/layout_N_T_/parent/child/layout(if present)_N_T_/parent/child(page)revalidatePath('/parent')writes the_N_T_/parentmarker, which matches the layout tag carried by every child render — that's what makes parent-path revalidation propagate.Repro
/parent/page.tsxand/parent/child/page.tsx, both callingfetch(url, { next: { revalidate: 3600 } })(no explicittags)./parent/childto populate the fetch cache.revalidatePath('/parent')from a server action or route handler./parent/child.Expected: the fetch in
/parent/childre-issues to the origin.Actual: the cached fetch result is reused.
The exact-path case (
revalidatePath('/parent/child')then re-rendering/parent/child) works correctly post-#917.Why this matters
Users who test path revalidation at the page level will see it work and assume the nested case works too. The failure mode is silent stale data — exactly the bug
revalidatePath()is supposed to prevent.Status
Not a regression — the nested case was also broken before #917 (where
revalidatePath()invalidated zero soft-tagged fetches). #917 is a strict improvement; this issue tracks the remaining gap.Proposed fix sketch
__pageCacheTags.cleanPathnameand inject it intosetCurrentFetchSoftTagsalongside the page tag.Either way, the fix is contained to the App Router entry template +
__pageCacheTagscallers; the cache-handler side already treats soft tags as read-time misses without persisting them on entries.References
getImplicitTagspatch-fetchpassessoftTags: implicitTags?.tags