-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Closed
Labels
Description
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
):
cacheComponents
forces us to choose between dynamic vs static rendering if we're doing data fetching or accessing the current time. If we don't make a choice, we get the error described in Next.js cacheComponents (dynamicIO) dehydration error #9457. ("Cannot infer intended usage of current time withDate.now()
,Date()
, ornew Date()
in a Server Component" when callingdehydrate(queryClient)
.)- if we opt for dynamic rendering it's fine (see Next.js cacheComponents (dynamicIO) dehydration error #9457 (comment))
- if we choose static rendering by adding
'use cache'
we get the error described here
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 runnext build
andnext start
to see this). - If I
await
the prefetch (as in the repro) then I get the same error withuseQuery
anduseSuspenseQuery
- If I call
useSuspenseQuery
and don't await the prefetching (as per the original prefetching example) I get the same error as above when runningnext build
. But there's a different error withnext 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:- "Error: Route "/": A component accessed data, headers, params, searchParams, or a short-lived cache without a Suspense boundary nor a "use cache" above it. See more info: https://nextjs.org/docs/messages/next-prerender-missing-suspense"