Skip to content

stale _payload.json?{buildId} on client navigation after ISR revalidation #35352

Description

@MichaelDickBasecom

Environment

System Version
Node.js version 22.x
Package manager bun
Nuxt version 4.4.8
Nitro version 2.13.4
Deployment target Vercel (vercel preset)

Relevant config:
experimental.payloadExtraction: 'client', routeRules: { '/': { isr: 120 }, '/b': { isr: 120 } }

Reproduction

Repo: https://github.com/MichaelDickBasecom/nuxt-isr-payload-buildid-repro
Live deployment: https://nuxt-isr-payload-buildid-repro.vercel.app/

Note

This bug requires a Vercel deployment with ISR. It does not reproduce in nuxt dev or StackBlitz.

  1. Deploy the repo to Vercel.
  2. Hard-reload /, then client-navigate A → B → A (warms the browser cache for /_payload.json?{buildId}).
  3. Wait > 2 minutes (ISR TTL is 120s).
  4. Client-navigate A → B via <NuxtLink> (not a full reload).
  5. Observe Page B's timestamp — it stays stale.
  6. Hard-reload /b — timestamp updates to the fresh ISR value.

Describe the bug

On ISR routes deployed to Vercel, client-side navigation fetches the page payload via /_payload.json?{buildId} using fetch(..., { cache: 'force-cache' }) (see nuxt/dist/app/composables/payload.js). The buildId query param only changes on deploy — not when ISR revalidates the page.

After the ISR TTL expires and the HTML cache is revalidated, client navigation still serves a stale payload from the browser's HTTP cache for the ?{buildId} URL. A hard reload returns fresh data because the HTML payload is inlined (payloadExtraction: 'client') from the revalidated ISR response.

Expected behavior: After ISR revalidation, client-side navigation should show the same fresh data as a hard reload.

Actual behavior: Client navigation shows stale useFetch/useAsyncData data from a cached /_payload.json?{buildId} response. The stale timestamp is visible on the page without opening DevTools.

This affects any ISR/SWR route using payload extraction with client-side navigation — e.g. CMS content, product listings, or any data fetched during SSR that lands in _payload.json.

payloadExtraction: 'client' (Nuxt 4.4, PR #34410) fixes the double-fetch on first load but does not fix stale payloads on subsequent client navigations.

Additional context

Related issues (different root cause / symptom):

  • #34496 / PR #34751 — payload URL drops query params on ISR/SWR routes (wrong payload for ?page=2, not stale-after-TTL)
  • #34189 — SWR disk cache not invalidating on 404/unpublish
  • #15427 — original stale _payload.json reports that led to ?buildId

Logs

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions