vercel / next.js

The React Framework
https://nextjs.org
MIT License
124.62k stars 26.6k forks source link

revalidateTag() cannot be relied upon to work – frequently will only revalidate the first affected tag visited, not any of the subsequent page visits #60834

Open simonhrogers opened 7 months ago

simonhrogers commented 7 months ago

Link to the code that reproduces this issue

https://github.com/simonhrogers/Matt-Carey-Williams/tree/revalidate-bug-report

To Reproduce

This is using Sanity’s own template repository for the App router, and they claim this is a Next/Vercel issue.

Current vs. Expected behavior

Only the first page visited by an array of tags is updated, after this, no number of refreshes will update the other tagged pages.

I expect all pages to be revalidated. Revalidate reports 200 in Vercel function logs for each affected page.

Verify canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: x64
  Version: Darwin Kernel Version 21.4.0: Fri Mar 18 00:45:05 PDT 2022; root:xnu-8020.101.4~15/RELEASE_X86_64
Binaries:
  Node: 20.10.0
  npm: 10.2.3
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 14.0.4-canary.26
  eslint-config-next: 14.0.3
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.3.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

App Router

Which stage(s) are affected? (Select all that apply)

Vercel (Deployed)

Additional context

No response

mordechaim commented 7 months ago

The Vercel team fixed a serious bug today, which was released on the most recent Canary channel.

It might be worth checking if this issue was also resolved.

akawalsky commented 4 months ago

I'm seeing unreliable revalidateTag functionality when called via a route. Sometimes, for certain tags, the pages using fetch calls reliant on those tags do not update at all. I then have to manually purge the cache in the Vercel UI. This seems to be happening transiently and is difficult to reproduce on demand.

benjitastic commented 4 months ago

Same. I don't have any more specific details to add since it's intermittent and happens on our production environment and we need to immediately resolve it with manually purging cache in the Vercel UI. But it is 100% a persistent and frustrating issue where revalidateTag does not clear the cache successfully on some server side fetch() calls.

The fact that revalidateTag from import { revalidateTag } from 'next/cache' is fire and forget (i.e. cannot be awaited) and does not return a status message makes this continue to be the black box that it is.

Would be ideal if revalidateTag returned a status and also some form of request ID so that we can submit useful tickets to Vercel support instead and include that ID instead of just us continuing to say that "revalidateTag doesn't work"

seivad commented 4 months ago

Hey I've noticed the following issues with using unstable_cache() and revalidateTag (and Path too):

Server Action on form: If I do a server action from a form and use the revalidateTag(...) in the action it will dump the cache when pulling that data in and on page.tsx.

Server Action via Fetch Request from Form: if I submit a form which calls a api route /api/v1/xxx/xxx to do a semantically correct form submission (i.e. PUT / DELETE, instead of everything being a POST), and that route uses a function from actions folder just like above and calls revalidateTag(...) the page that the client form was on won't dump the unstable_cache.

I have tried revalidateTag(...) and revalidatePath(...) and this seems to be consistent behaviour when running locally.

Expected behaviour: Wherever I call revalidateTag(...) from, whether it's from a fetch() from inside of a 'use client' component or from a

, the page.tsx that has the unstable_cache should grab a new copy of the data it is caching.

this framework feels so undercooked at the moment, needs way way more time in the oven.

sudeepgumaste commented 4 months ago

Hi, I seem to have a similar problem with revalidateTag. I have this api route with the following code

export async function GET(request: NextRequest) {
  const url = new URL(request.url);
  const secret = url.searchParams.get('secret');
  const tags: string[] = JSON.parse(url.searchParams.get('tags') || '[]');

  if (secret !== process.env.REVALIDATE_TAG_SECRET) {
    return Response.json({ message: 'Invalid secret' }, { status: 401 });
  }

  if (tags?.length === 0) {
    return Response.json({ message: 'Missing tag param' }, { status: 400 });
  }

  tags.forEach((tag) => {
    revalidateTag(tag);
  });

  return Response.json({ revalidated: true, now: Date.now() });
}

which I am hittng from my strapi collection's onUpdate lifecycle hook. I had set it up so that any blog with a particular slug used as a tag gets invalidated. I'm not sure if I'm doing something wrong but when I rebuild from vercel ui ignoring the cache I have the latest contents in the article and as soon as I make a change and save on strapi which causes the lifecycle hook to hit the revalidation API, the cache gets invalidated but it starts using the cache that I had ignored. Is this an issue with Vercel or Next?

mattinannt commented 2 months ago

Also for us, revalidateTag() is not triggered reliably on Vercel (nextjs 15rc). We call it with a server action and sometimes loop through multiple revalidateTag operations based on the action and they sometimes don't revalidate the tag without the problem being reproducible. A good guess could be that the revalidateTag command got lost or didn't reach the cache, so being able to await it would also be great for us.