#99352·Next.js

cacheHandlers[*].updateTags only receives the first profile group when one request revalidates tags with different profiles

Author: uaoaCreated Sep 28, 2026Updated Sep 28, 2026
LabelsPerformance

Link to the code that reproduces this issue

https://github.com/uaoa/next-updatetags-repro

To Reproduce

  1. Clone the repo, run npm install, npx next build, npx next start -p 3457.

  2. Open http://localhost:3457 and click "Revalidate a and b".

  3. The server action in app/actions.ts calls, in one request:

    updateTag('a'); revalidateTag('b', { expire: 0 });

  4. Watch the server log. cache-handler.mjs wraps Next's own createDefaultCacheHandler and only logs every updateTags(tags, durations) call.

Current vs. Expected behavior

Current: the custom cache handler's updateTags is called only with ["a"]. Tag b never reaches it:

[cache-handler] updateTags ["a"] null

Expected: updateTags is called once per profile group:

[cache-handler] updateTags ["a"] null [cache-handler] updateTags ["b"] {"expire":0}

With the built-in handler the bug is invisible, because b is still invalidated locally through the shared tags manifest. It shows up with any custom handler that relies on updateTags, e.g. one that propagates invalidations across instances (Redis). In a multi-instance deployment b then stays stale on every other instance.

Cause: in dist/server/revalidation-utils.js, const handlers = getCacheHandlers() returns handlersSet.values() (a one-shot iterator; a generator in dev). The loop over profile groups consumes it in the first group, so every later group iterates an empty iterator. Suggested fix: const handlers = Array.from(getCacheHandlers() ?? []).

Provide environment information

bash
Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 27.0.0: Tue Aug 11 21:05:48 PDT 2026; root:xnu-13432.1.9~1/RELEASE_ARM64_T6041
  Available memory (MB): 24576
  Available CPU cores: 12
Binaries:
  Node: 24.18.0
  npm: 11.16.0
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 16.4.0-canary.51 // Latest available version is detected (16.4.0-canary.51).
  eslint-config-next: N/A
  react: 19.3.0
  react-dom: 19.3.0
  typescript: 5.9.3
Next.js Config:
  output: N/A

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

Use Cache, Performance

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

next start (local), next dev (local)

Additional context

Reproduced on 16.3.5 and on the latest canary (16.4.0-canary.51); the relevant code in revalidation-utils.js and use-cache/handlers.js is unchanged between them.

Found while running Next in several processes behind a load balancer (self-hosted, pm2 cluster) with a custom cache handler that shares tag invalidations through Redis: tags revalidated in the same request as an updateTag with a different profile never reached the other processes.

Workaround we use for now: intercept local writes to the shared tags manifest instead of relying on updateTags.