Skip to content

Next.js cacheComponents: cannot prefetch and access query data underneath 'use cache' #9499

@mdj-uk

Description

@mdj-uk

Describe the bug

In the repro (based on prefetching example but with next canary and experimental.cacheComponents enabled) I

  • call await queryClient.prefetchQuery(...) in a server component marked 'use cache'
  • dehydrate query client and pass to client component
  • access query data with useQuery

It results in this server error:

## Error Type
Console Error

## Error Message
Route "/" used `Date.now()` inside a Client Component without a Suspense boundary above it. See more info here: https://nextjs.org/docs/messages/next-prerender-current-time-client


    at PokemonInfo (app/pokemon-info.tsx:7:28)
    at LogSafely (unknown:0:0)

## Code Frame
   5 |
   6 | export function PokemonInfo() {
>  7 |   const { data } = useQuery(pokemonOptions);
     |                            ^
   8 |   if (!data) return <div>No data</div>;
   9 |   return (
  10 |     <div>

Next.js version: 15.4.2-canary.16 (Webpack)

If I run the next dev server with debugging there's a more helpful stack trace in the debug console:

Error: Route "/" used `Date.now()` inside a Client Component without a Suspense boundary above it. See more info here: https://nextjs.org/docs/messages/next-prerender-current-time-client
    at io (/project/workspace/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/server/node-environment-extensions/utils.js:78:146)
    at now (/project/workspace/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/server/node-environment-extensions/date.js:19:27)
    at timeUntilStale (webpack-internal:///(ssr)/./node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/utils.js:39:55)
    at Query.isStaleByTime (webpack-internal:///(ssr)/./node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/query.js:115:70)
    at isStale (webpack-internal:///(ssr)/./node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/queryObserver.js:454:111)
    at shouldFetchOn (webpack-internal:///(ssr)/./node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/queryObserver.js:446:53)
    at shouldFetchOnMount (webpack-internal:///(ssr)/./node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/queryObserver.js:441:78)
    at QueryObserver.createResult (webpack-internal:///(ssr)/./node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/queryObserver.js:245:40)
    at QueryObserver.updateResult (webpack-internal:///(ssr)/./node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/queryObserver.js:371:29)
    at QueryObserver.setOptions (webpack-internal:///(ssr)/./node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/queryObserver.js:116:10)
    at new QueryObserver (webpack-internal:///(ssr)/./node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/queryObserver.js:31:10)
    at useBaseQuery.useState (webpack-internal:///(ssr)/./node_modules/.pnpm/@[email protected][email protected]/node_modules/@tanstack/react-query/build/modern/useBaseQuery.js:43:38)
    at useReducer (/project/workspace/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/compiled/next-server/app-page-experimental.runtime.dev.js:2:86580)
    at Object.useState (/project/workspace/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/compiled/next-server/app-page-experimental.runtime.dev.js:2:316482)
    at exports.useState (/project/workspace/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/compiled/next-server/app-page-experimental.runtime.dev.js:2:392162)
    at useBaseQuery (webpack-internal:///(ssr)/./node_modules/.pnpm/@[email protected][email protected]/node_modules/@tanstack/react-query/build/modern/useBaseQuery.js:42:59)
    at useQuery (webpack-internal:///(ssr)/./node_modules/.pnpm/@[email protected][email protected]/node_modules/@tanstack/react-query/build/modern/useQuery.js:11:74)
    at PokemonInfo (webpack-internal:///(ssr)/./app/pokemon-info.tsx:13:85)
    ...

The error in next build output looks equivalent:

Error: Route "/" used `Date.now()` inside a Client Component without a Suspense boundary above it. See more info here: https://nextjs.org/docs/messages/next-prerender-current-time-client
    at h (.next/server/chunks/300.js:1:125321)
    at h.isStaleByTime (.next/server/chunks/300.js:1:47258)
    at n (.next/server/app/page.js:1:43090)
    at l (.next/server/app/page.js:1:42911)
    at k (.next/server/app/page.js:1:42740)
    at j.createResult (.next/server/app/page.js:1:39855)
    at j.updateResult (.next/server/app/page.js:1:41731)
    at j.setOptions (.next/server/app/page.js:1:37851)
    at new j (.next/server/app/page.js:1:36675)
    at <unknown> (.next/server/app/page.js:1:6233)
    at l (.next/server/app/page.js:1:6220)
    at g (.next/server/app/page.js:2:9093)
    at g (.next/server/app/page.js:1:3551)

Your minimal, reproducible example

https://codesandbox.io/p/github/mdj-uk/nextjs-prefetch/main

Steps to reproduce

  • open sandbox
  • open preview (of port 3000) and load home page

Expected behavior

Should be able to prefetch in server component marked 'use cache' and render query data in client component in prerender phase without error. (i.e. query data should be in SSG/ISR output)

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

N/A

Tanstack Query adapter

react-query

TanStack Query version

v5.83.0

TypeScript version

5.8.3

Additional context

My understanding of cacheComponents (previously dynamicIO):

About this error:

  • Note that there's no error if you remove the prefetching, or if you keep the prefetching but remove the component which calls useQuery. It's the combination of prefetching + useQuery underneath 'use cache' which causes the problem
  • I can make the error go away by wrapping PokemonInfo in a suspense boundary with fallback, but that doesn't help as it bails out of server rendering thePokemonInfo and renders the fallback instead (You'll need to run next build and next start to see this).
  • If I await the prefetch (as in the repro) then I get the same error with useQuery and useSuspenseQuery
  • If I call useSuspenseQuery and don't await the prefetching (as per the original prefetching example) I get the same error as above when running next build. But there's a different error with next dev. The dev error is confusing as it doesn't provide a stack trace, and it tells you to add 'use cache' which is already there:

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions