Link to the code that reproduces this issue
https://github.com/iamibi/next.js/tree/repro/fetch-options-mutation
To Reproduce
The reproduction enables Cache Components and passes the same module-level options object to two fetches. These are the
relevant files:
// next.config.ts
const nextConfig = { cacheComponents: true }
export default nextConfig
// app/fetch-options.ts
export const fetchOptions: RequestInit = {
next: { revalidate: 3600, tags: ['shared'] },
}
// app/page.tsx
import { fetchOptions } from './fetch-options'
async function getRandom(id: string) {
const response = await fetch(`https://next-data-api-endpoint.vercel.app/api/random?id=${id}`, fetchOptions)
return response.text()
}
export default async function Home() {
const first = await getRandom('first')
const second = await getRandom('second')
return (
<>
<p id="first">{first}</p>
<p id="second">{second}</p>
</>
)
}
Clone the standalone reproduction branch, run the build from a clean cache, then start dev from a clean cache and
request the page twice. Do not use a browser hard reload: it sends cache-control: no-cache and can bypass the dev
fetch cache for another reason.
git clone --branch repro/fetch-options-mutation --single-branch https://github.com/iamibi/next.js.git
cd next.js
npm install
npx next info
rm -rf .next && npx next build
rm -rf .next && npx next dev
# In a second terminal after `next dev` starts:
curl -s http://localhost:3000/ | grep -o '<p id="[a-z]*">[^<]*</p>'
curl -s http://localhost:3000/ | grep -o '<p id="[a-z]*">[^<]*</p>'
Recorded build output on next@16.4.0-canary.48 (Turbopack), shortened to the relevant lines:
▲ Next.js 16.4.0-canary.48 (Turbopack)
- Cache Components enabled
Error: Route "/": Next.js encountered uncached or runtime data during prerendering.
Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error
Export encountered an error on /page: /, exiting the build.
Recorded dev values on the same version, grouped by request (each value changes despite the one-hour revalidate
setting):
req 1: <p id="first">0.5803781611531635</p> <p id="second">0.8049157565767228</p>
req 2: <p id="first">0.8195101744169244</p> <p id="second">0.9509479308231455</p>
Error: Route "/": Next.js encountered uncached data during prerendering.
As a control, replace fetchOptions at the call site with a fresh { next: { revalidate: 3600, tags: ['shared'] } }
object, clear .next, and rebuild. The recorded route table then shows the static route below; dev values remain stable
across requests.
Route (app) Revalidate Expire
┌ ○ / 1h 1y
└ ○ /_not-found
Current vs. Expected behavior
The patched server fetch receives the caller's init object by reference. On a cache miss, it deletes init.next while preparing the origin request; on the edge runtime it can also delete init.cache. The first call therefore changes a reusable options object, and later calls lose their revalidate and tags settings. The build reports:
“Next.js encountered uncached or runtime data during prerendering.” In dev, requests refetch and report a blocking route. A frozen options object also throws under the unit test and a webpack build.
The caller's options should remain intact after fetch. Both calls should use the intended cache settings, the page should prerender as it does with inline options, and dev requests should reuse the fetch cache without a blocking-route error.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.6.0: Tue Aug 18 17:51:33 PDT 2026; root:xnu-12377.161.15.700.19~2/RELEASE_ARM64_T8132
Available memory (MB): 24576
Available CPU cores: 10
Binaries:
Node: 24.19.0
npm: N/A
Yarn: N/A
pnpm: 11.19.0
Relevant Packages:
next: 16.4.0-canary.48
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)
cacheComponents, Runtime
Which stage(s) are affected? (Select all that apply)
next dev (local), next build (local)
Additional context
The mutation is in packages/next/src/server/lib/patch-fetch.ts: the origin fetch needs a stripped copy, but the deletion is currently performed on the caller's object. A separate symptom without cacheComponents is that the second fetch-cache entry loses its tag, so tag revalidation no longer targets it. Clearing .next is necessary when reproducing because a warm fetch-cache hit returns before the mutation. A proposed fix that copies init before removing those fields, with unit and e2e tests, is in the linked pull request. This issue concerns fetch options passed as init, rather than a Request object's separate next handling.
Link to the code that reproduces this issue
https://github.com/iamibi/next.js/tree/repro/fetch-options-mutation
To Reproduce
The reproduction enables Cache Components and passes the same module-level options object to two fetches. These are the
relevant files:
Clone the standalone reproduction branch, run the build from a clean cache, then start dev from a clean cache and
request the page twice. Do not use a browser hard reload: it sends
cache-control: no-cacheand can bypass the devfetch cache for another reason.
Recorded build output on
next@16.4.0-canary.48(Turbopack), shortened to the relevant lines:Recorded dev values on the same version, grouped by request (each value changes despite the one-hour revalidate
setting):
As a control, replace
fetchOptionsat the call site with a fresh{ next: { revalidate: 3600, tags: ['shared'] } }object, clear
.next, and rebuild. The recorded route table then shows the static route below; dev values remain stableacross requests.
Current vs. Expected behavior
The patched server
fetchreceives the caller'sinitobject by reference. On a cache miss, it deletesinit.nextwhile preparing the origin request; on the edge runtime it can also deleteinit.cache. The first call therefore changes a reusable options object, and later calls lose theirrevalidateandtagssettings. The build reports:“Next.js encountered uncached or runtime data during prerendering.” In dev, requests refetch and report a blocking route. A frozen options object also throws under the unit test and a webpack build.
The caller's options should remain intact after
fetch. Both calls should use the intended cache settings, the page should prerender as it does with inline options, and dev requests should reuse the fetch cache without a blocking-route error.Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 25.6.0: Tue Aug 18 17:51:33 PDT 2026; root:xnu-12377.161.15.700.19~2/RELEASE_ARM64_T8132 Available memory (MB): 24576 Available CPU cores: 10 Binaries: Node: 24.19.0 npm: N/A Yarn: N/A pnpm: 11.19.0 Relevant Packages: next: 16.4.0-canary.48 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)
cacheComponents, Runtime
Which stage(s) are affected? (Select all that apply)
next dev (local), next build (local)
Additional context
The mutation is in
packages/next/src/server/lib/patch-fetch.ts: the origin fetch needs a stripped copy, but the deletion is currently performed on the caller's object. A separate symptom withoutcacheComponentsis that the second fetch-cache entry loses its tag, so tag revalidation no longer targets it. Clearing.nextis necessary when reproducing because a warm fetch-cache hit returns before the mutation. A proposed fix that copiesinitbefore removing those fields, with unit and e2e tests, is in the linked pull request. This issue concernsfetchoptions passed asinit, rather than aRequestobject's separatenexthandling.