nextjs - ✅(Solved) Fix Allow dynamic APIs (`cookies()`, `headers()`) inside `"use cache"` when Draft Mode is enabled [1 pull requests, 14 comments, 9 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#87742Fetched 2026-04-08 02:06:14
View on GitHub
Comments
14
Participants
9
Timeline
38
Reactions
11
Timeline (top)
commented ×14subscribed ×12labeled ×5unsubscribed ×3

Error Message

Error: Route / used cookies() inside "use cache". Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use cookies() outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache

Root Cause

  1. The cache is already bypassed — PR #77141 correctly skips cache reads and writes when Draft Mode is enabled
  2. Draft Mode inherently requires dynamic behavior — The whole point of Draft Mode is to render fresh, request-specific content
  3. This was the previous behavior — With the fetch cache, Draft Mode allowed reading cookies to pass preview tokens to CMS APIs
  4. draftMode().isEnabled is already allowed — As noted in PR #73324, draftMode().isEnabled is permitted inside "use cache" because "when it's on, it switches everything to dynamic rendering anyway, so that prerender/cache entry is ignored." The same logic should apply to other dynamic APIs.

Fix Action

Fix / Workaround

  • #76581 — "use cache" directive is not bypassed when draftMode is enabled (fixed)
  • PR #77141 — Bypass "use cache" caches when Draft Mode is enabled
  • PR #73324 — Allow reading draftMode status (established that draftMode().isEnabled is not a "real" dynamic API in cache contexts)
  • #86739 — Docs: How to intentionally block in Cache Components? (discusses the <Suspense fallback={null}> workaround pattern)
  • brunorzn/nextjs-draftmode-devmode-example#1SuspendedDraftMode wrapper pattern (does not solve this issue)

PR fix notes

PR #1: Use Suspense to make the draft version of the page non-blocking

Description (problem / solution / changelog)

Okay I tracked it down! Few things going on here.

First, the reason you're seeing the error in dev is because the draft mode version of the page is blocking. If you add

await new Promise((resolve) => setTimeout(resolve, 2_000));

to getRandomData and run the app in prod, you'll see that the page blocks when draft mode is enabled. We don't show the error in prod because the error is really a dev-time feature intended to help you not add blocking routes to your app. But the idea is that in draft mode, you're blocking on getRandomData, so it triggers the error just like if you were blocking on anything else.

The fix is to add Suspense for the draft-mode path of the code, since it accesses uncached data. You can use a null fallback if you like, or choose to include more of the page in the shell. But either way, when folks visit the draft mode page they'll also get a faster load.

I guess there's an argument here that it's a bit strange that you need to code two paths for your app just to account for draft mode, but today, Next doesn't distinguish one kind of blocking code from another. So it's the getRandomData code that's blocking, and that's what the error is surfacing.

Secondly, it seems there's a bug in current latest Next 16, because even after the refactor I was seeing the error from a faulty prerender when draftMode was enabled. Seemed to be a bug where the prerender was getting the wrong value of draftMode on the server. I bumped Next to the latest canary version and it all works, so this should make its way into a stable release soon.

Let me know if you have any more questions!

Changed files

  • app/layout.tsx (modified, +0/-1)
  • app/page.tsx (modified, +28/-11)
  • package.json (modified, +3/-2)
  • pnpm-lock.yaml (modified, +42/-41)

Code Example

Error: Route / used `cookies()` inside "use cache". Accessing Dynamic data
sources inside a cache scope is not supported. If you need this data inside a
cached function use `cookies()` outside of the cached function and pass the
required dynamic data in as an argument. See more info here:
https://nextjs.org/docs/messages/next-request-in-use-cache

---

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.1.0: Mon Oct 20 19:32:41 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T6000
  Available memory (MB): 32768
  Available CPU cores: 10
Binaries:
  Node: 24.5.0
  npm: 11.5.1
  Yarn: 4.7.0
  pnpm: 10.8.0
Relevant Packages:
  next: 16.1.1-canary.5 // Latest available version is detected (16.1.1-canary.5).
  eslint-config-next: N/A
  react: 19.2.3
  react-dom: 19.2.3
  typescript: 5.9.3
Next.js Config:
  output: N/A
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/angeloashmore/cache-components-draft-mode-dynamic-apis

To Reproduce

  1. Visit http://localhost:3000/ — page renders without cookies()
  2. Visit http://localhost:3000/api/draft — enables Draft Mode
  3. Visit http://localhost:3000/ — page renders with cookies() and throws

Current vs. Expected behavior

Current behavior:

When Draft Mode is enabled and I try to call cookies() inside a "use cache" function, Next.js throws an error:

Error: Route / used `cookies()` inside "use cache". Accessing Dynamic data
sources inside a cache scope is not supported. If you need this data inside a
cached function use `cookies()` outside of the cached function and pass the
required dynamic data in as an argument. See more info here:
https://nextjs.org/docs/messages/next-request-in-use-cache

This error occurs even though Draft Mode is enabled, which means the cache is already being bypassed (as fixed in #76581 / PR #77141).

Expected behavior:

When Draft Mode is enabled, dynamic APIs like cookies() and headers() should be allowed inside "use cache" functions, since:

  1. The cache is already bypassed — PR #77141 correctly skips cache reads and writes when Draft Mode is enabled
  2. Draft Mode inherently requires dynamic behavior — The whole point of Draft Mode is to render fresh, request-specific content
  3. This was the previous behavior — With the fetch cache, Draft Mode allowed reading cookies to pass preview tokens to CMS APIs
  4. draftMode().isEnabled is already allowed — As noted in PR #73324, draftMode().isEnabled is permitted inside "use cache" because "when it's on, it switches everything to dynamic rendering anyway, so that prerender/cache entry is ignored." The same logic should apply to other dynamic APIs.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.1.0: Mon Oct 20 19:32:41 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T6000
  Available memory (MB): 32768
  Available CPU cores: 10
Binaries:
  Node: 24.5.0
  npm: 11.5.1
  Yarn: 4.7.0
  pnpm: 10.8.0
Relevant Packages:
  next: 16.1.1-canary.5 // Latest available version is detected (16.1.1-canary.5).
  eslint-config-next: N/A
  react: 19.2.3
  react-dom: 19.2.3
  typescript: 5.9.3
Next.js Config:
  output: N/A

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

Cookies, Draft Mode, cacheComponents, Headers

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

next dev (local), Vercel (Deployed), Other (Deployed), next start (local)

Additional context

This is a common pattern when integrating with headless CMS platforms (Prismic, Contentful, Sanity, Storyblok, etc.):

  1. Editor clicks "Preview" in the CMS → CMS redirects to /api/draft?token=xyz
  2. API route enables Draft Mode and stores the preview token in a cookie
  3. Page renders with Draft Mode enabled → needs to read the preview token cookie to authenticate with the CMS preview API

With full-page caching via "use cache", this pattern is broken because we cannot read the preview token cookie, even though Draft Mode has already bypassed the cache.

Proposed Solution:

When Draft Mode is enabled, the "use cache" boundary should behave as if it doesn't exist — allowing dynamic APIs (cookies(), headers(), searchParams, etc.) without throwing an error.

This is consistent with the existing behavior where:

  • Cache reads are skipped when Draft Mode is enabled
  • Cache writes are skipped when Draft Mode is enabled
  • draftMode().isEnabled is allowed inside "use cache"

Related issues and PRs:

  • #76581 — "use cache" directive is not bypassed when draftMode is enabled (fixed)
  • PR #77141 — Bypass "use cache" caches when Draft Mode is enabled
  • PR #73324 — Allow reading draftMode status (established that draftMode().isEnabled is not a "real" dynamic API in cache contexts)
  • #86739 — Docs: How to intentionally block in Cache Components? (discusses the <Suspense fallback={null}> workaround pattern)
  • brunorzn/nextjs-draftmode-devmode-example#1SuspendedDraftMode wrapper pattern (does not solve this issue)

extent analysis

TL;DR

The most likely fix is to modify the Next.js "use cache" directive to allow dynamic APIs like cookies() when Draft Mode is enabled.

Guidance

  • Review the proposed solution in the issue, which suggests that the "use cache" boundary should be bypassed when Draft Mode is enabled, allowing dynamic APIs without throwing an error.
  • Investigate the related issues and PRs, such as #76581, PR #77141, and PR #73324, to understand the existing behavior and potential solutions.
  • Consider using a workaround pattern, such as the <Suspense fallback={null}> pattern discussed in #86739, to intentionally block cache components.
  • Verify that the draftMode().isEnabled check is allowed inside "use cache" and apply similar logic to other dynamic APIs.

Example

No code snippet is provided as the issue does not contain a specific code example that can be modified to fix the issue.

Notes

The issue is specific to Next.js version 16.1.1-canary.5, and the proposed solution may not be applicable to other versions. Additionally, the issue is related to the interaction between Draft Mode, cache components, and dynamic APIs, which may require a deeper understanding of Next.js internals.

Recommendation

Apply the proposed solution to modify the "use cache" directive to allow dynamic APIs when Draft Mode is enabled, as it is consistent with the existing behavior of bypassing cache reads and writes when Draft Mode is enabled.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

nextjs - ✅(Solved) Fix Allow dynamic APIs (`cookies()`, `headers()`) inside `"use cache"` when Draft Mode is enabled [1 pull requests, 14 comments, 9 participants]