Skip to content

Allow dynamic APIs (cookies(), headers()) inside "use cache" when Draft Mode is enabled #87742

@angeloashmore

Description

@angeloashmore

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 Bypass "use cache" caches when Draft Mode is enabled #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 fix(after): allow reading draftMode status in after #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:

Metadata

Metadata

Assignees

No one assigned

    Labels

    CookiesRelated to the async cookies() function.Draft ModeRelated to Draft Mode.HeadersRelated to the async headers() function.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions