Skip to content

Conversation

@chosule
Copy link

@chosule chosule commented Jan 27, 2026

Fixes #8825

Note: This solution was discussed and approved by @TkDodo in Discussion #10027

Problem

When prefetchInfiniteQuery fails on the server, useSuspenseInfiniteQuery on the client doesn't return the correct infinite query structure ({ pages: [], pageParams: [] }), causing a runtime error when accessing data.pages:

TypeError: Cannot read properties of undefined (reading 'length')

Root Cause

Infinite query behavior information gets lost during hydration:

  1. infiniteQueryBehavior is attached when prefetchInfiniteQuery runs on the server
  2. This behavior info isn't preserved during dehydration
  3. On the client, it gets restored as a regular query during hydration
  4. Error occurs when data is accessed before InfiniteQueryObserver attaches the behavior

Solution

Set up infinite query behavior at hydration time to guarantee correct data structure for both success and failure cases.

Changes

1. Added queryType field to DehydratedQuery

  • Metadata to identify infinite queries
  • Stores 'query' | 'infiniteQuery' value

2. Auto-detect query type during dehydration

  • Checks for initialPageParam presence to identify infinite queries
  • Stores result in queryType field

3. Auto-configure behavior during hydration

  • Attaches infiniteQueryBehavior when queryType is 'infiniteQuery'

4. Handle failed promises

  • Rejected promises aren't passed as initialPromise
  • Allows automatic retry on the client

Modified Files

  1. packages/query-core/src/hydration.ts
  2. packages/query-core/src/__tests__/hydration.test.tsx

Tests

All 35 tests passing (including 2 new tests)

New tests added:

  • should preserve queryType for infinite queries during hydration
  • should attach infiniteQueryBehavior during hydration

Checklist

  • Added queryType: 'query' | 'infiniteQuery' field to DehydratedQuery
  • Auto-detect infinite queries during dehydration by checking initialPageParam
  • Auto-configure infiniteQueryBehavior for infinite queries during hydration
  • Added test cases for hydrated infinite query behavior
  • Guarantee correct data structure for both success and failure cases

Summary by CodeRabbit

  • Bug Fixes

    • Preserve infinite-query pagination and behavior during SSR hydration so hydrated clients retain pages and cursors.
  • Tests

    • Added hydration tests to validate infinite query preservation and correct post-hydration fetching.
  • Chores

    • Added release metadata documenting this patch release.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Jan 27, 2026

🦋 Changeset detected

Latest commit: 7c41b00

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 19 packages
Name Type
@tanstack/query-core Patch
@tanstack/angular-query-experimental Patch
@tanstack/query-async-storage-persister Patch
@tanstack/query-broadcast-client-experimental Patch
@tanstack/query-persist-client-core Patch
@tanstack/query-sync-storage-persister Patch
@tanstack/react-query Patch
@tanstack/solid-query Patch
@tanstack/svelte-query Patch
@tanstack/vue-query Patch
@tanstack/angular-query-persist-client Patch
@tanstack/react-query-persist-client Patch
@tanstack/solid-query-persist-client Patch
@tanstack/svelte-query-persist-client Patch
@tanstack/react-query-devtools Patch
@tanstack/react-query-next-experimental Patch
@tanstack/solid-query-devtools Patch
@tanstack/svelte-query-devtools Patch
@tanstack/vue-query-devtools Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 27, 2026

📝 Walkthrough

Walkthrough

Adds explicit handling for infinite queries in de/rehydration: dehydrated queries now include a queryType flag, hydration restores that flag and applies infiniteQueryBehavior for infinite queries, and tests were added to validate structural and behavioral preservation across dehydrate→hydrate flows.

Changes

Cohort / File(s) Summary
Metadata
\.changeset/stupid-seals-live.md
New changeset documenting a patch release for @tanstack/query-core, noting preservation of infinite query behavior during SSR hydration.
Core Hydration Logic
packages/query-core/src/hydration.ts
DehydratedQuery gains `queryType?: 'query'
Hydration Tests
packages/query-core/src/__tests__/hydration.test.tsx
Added two tests: one asserts queryType/pages/pageParams preserved for prefetched infinite queries; the other asserts infiniteQueryBehavior is attached and fetchInfiniteQuery returns correct pages/pageParams after hydration.

Sequence Diagram(s)

sequenceDiagram
  participant Server as Server (prefetch)
  participant Dehydrator as Dehydrator
  participant Serialized as Dehydrated State
  participant Client as Client (hydrate)
  participant QueryClient as QueryClient

  Server->>Dehydrator: prefetchInfiniteQuery (pages, pageParams)
  Dehydrator->>Serialized: dehydrate(query + queryType:'infiniteQuery')
  Serialized-->>Client: send dehydrated state
  Client->>QueryClient: hydrate(state)
  QueryClient->>QueryClient: restore query (read queryType)
  alt queryType == 'infiniteQuery'
    QueryClient->>QueryClient: apply infiniteQueryBehavior to restored options
  end
  Client->>QueryClient: fetchInfiniteQuery() -> uses restored behavior and pages/pageParams
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • TkDodo
  • Ephem

Poem

"🐰 I hopped through state both wide and deep,
Saved pages and cursors for you to keep,
Dehydrate, hydrate — no data astray,
Infinite hops now find their way,
Cheers — a rabbit's joyful leap!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix/infinite query hydration 8825' is clearly related to the main change, which fixes infinite query hydration during SSR by preserving infinite query behavior.
Description check ✅ Passed The PR description comprehensively covers the problem, root cause, solution, modified files, and includes passing tests; all required checklist items are marked complete.
Linked Issues check ✅ Passed The PR directly addresses #8825 by implementing all required objectives: detecting infinite queries during dehydration, auto-configuring behavior during hydration, and adding tests to verify correct data structure preservation.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing infinite query hydration; modified files are hydration.ts and hydration tests, with a changeset documenting the patch release.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

🧪 Unit Test Generation v2 is now available!

We have significantly improved our unit test generation capabilities.

To enable: Add this to your .coderabbit.yaml configuration:

reviews:
  finishing_touches:
    unit_tests:
      enabled: true

Try it out by using the @coderabbitai generate unit tests command on your code files or under ✨ Finishing Touches on the walkthrough!

Have feedback? Share your thoughts on our Discord thread!


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Jan 29, 2026

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit 161c143

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ❌ Failed 4m 20s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 2s View ↗

☁️ Nx Cloud last updated this comment at 2026-01-30 09:25:05 UTC

Comment on lines 258 to 267
const queryOptions: any = {
...client.getDefaultOptions().hydrate?.queries,
...options?.defaultOptions?.queries,
queryKey,
queryHash,
meta,
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we keep this inlined please and just conditionally assign behavior:

behavior: queryType === 'infiniteQuery'
  ? (infiniteQueryBehavior() as QueryBehavior<unknown, unknown, unknown>)
  : undefined,

Comment on lines 297 to 312
const isRejectedThenable =
promise &&
typeof promise === 'object' &&
'status' in promise &&
(promise as any).status === 'rejected'

if (!isRejectedThenable) {
query
.fetch(undefined, {
// RSC transformed promises are not thenable
initialPromise: Promise.resolve(promise).then((resolvedData) => {
return deserializeData(resolvedData)
}),
})
// Avoid unhandled promise rejections
.catch(noop)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t understand what this change has to do with infinite queries ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TkDodo
Applied your feedback! 🙏

You're right that the rejected promise handling wasn't directly related to #8825.
I've removed that part and inlined the behavior assignment as suggested.

Please take another look when you can!

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 30, 2026

More templates

@tanstack/angular-query-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-experimental@10074

@tanstack/eslint-plugin-query

npm i https://pkg.pr.new/@tanstack/eslint-plugin-query@10074

@tanstack/query-async-storage-persister

npm i https://pkg.pr.new/@tanstack/query-async-storage-persister@10074

@tanstack/query-broadcast-client-experimental

npm i https://pkg.pr.new/@tanstack/query-broadcast-client-experimental@10074

@tanstack/query-core

npm i https://pkg.pr.new/@tanstack/query-core@10074

@tanstack/query-devtools

npm i https://pkg.pr.new/@tanstack/query-devtools@10074

@tanstack/query-persist-client-core

npm i https://pkg.pr.new/@tanstack/query-persist-client-core@10074

@tanstack/query-sync-storage-persister

npm i https://pkg.pr.new/@tanstack/query-sync-storage-persister@10074

@tanstack/react-query

npm i https://pkg.pr.new/@tanstack/react-query@10074

@tanstack/react-query-devtools

npm i https://pkg.pr.new/@tanstack/react-query-devtools@10074

@tanstack/react-query-next-experimental

npm i https://pkg.pr.new/@tanstack/react-query-next-experimental@10074

@tanstack/react-query-persist-client

npm i https://pkg.pr.new/@tanstack/react-query-persist-client@10074

@tanstack/solid-query

npm i https://pkg.pr.new/@tanstack/solid-query@10074

@tanstack/solid-query-devtools

npm i https://pkg.pr.new/@tanstack/solid-query-devtools@10074

@tanstack/solid-query-persist-client

npm i https://pkg.pr.new/@tanstack/solid-query-persist-client@10074

@tanstack/svelte-query

npm i https://pkg.pr.new/@tanstack/svelte-query@10074

@tanstack/svelte-query-devtools

npm i https://pkg.pr.new/@tanstack/svelte-query-devtools@10074

@tanstack/svelte-query-persist-client

npm i https://pkg.pr.new/@tanstack/svelte-query-persist-client@10074

@tanstack/vue-query

npm i https://pkg.pr.new/@tanstack/vue-query@10074

@tanstack/vue-query-devtools

npm i https://pkg.pr.new/@tanstack/vue-query-devtools@10074

commit: 161c143

@chosule chosule force-pushed the fix/infinite-query-hydration-8825 branch from 161c143 to 7c41b00 Compare January 30, 2026 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Next.js: exception encountered in prefetchInfiniteQuery causes useSuspenseInfiniteQuery to fail

2 participants