cacheHandlers[*].updateTags only receives the first profile group when one request revalidates tags with different profiles
Link to the code that reproduces this issue
https://github.com/uaoa/next-updatetags-repro
To Reproduce
Clone the repo, run
npm install,npx next build,npx next start -p 3457.Open http://localhost:3457 and click "Revalidate a and b".
The server action in
app/actions.tscalls, in one request:updateTag('a'); revalidateTag('b', { expire: 0 });
Watch the server log.
cache-handler.mjswraps Next's owncreateDefaultCacheHandlerand only logs everyupdateTags(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
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/AWhich 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.
Source: vercel/next.js