Skip to content

fix(query-core): guard against undefined pages in hasNextPage/hasPreviousPage#11001

Open
ZacharyL2 wants to merge 1 commit into
TanStack:mainfrom
ZacharyL2:fix/infinite-query-undefined-pages
Open

fix(query-core): guard against undefined pages in hasNextPage/hasPreviousPage#11001
ZacharyL2 wants to merge 1 commit into
TanStack:mainfrom
ZacharyL2:fix/infinite-query-undefined-pages

Conversation

@ZacharyL2

@ZacharyL2 ZacharyL2 commented Jun 29, 2026

Copy link
Copy Markdown

Summary

hasNextPage / hasPreviousPage crash with TypeError: Cannot read properties of undefined (reading 'length') when state.data is a malformed InfiniteData whose pages is undefined.

The InfiniteData interface declares pages: Array<TData> as required, which is true for data produced by infiniteQueryBehavior's own fetch. But state.data can also be populated from outside that path — SSR hydration, a manual setQueryData, or a persisted/restored cache — where the object may not honor the type. When such data reaches getNextPageParam, the unconditional pages.length throws.

Notably, onFetch in the same file already anticipates this:

const oldPages = context.state.data?.pages || []
const oldPageParams = context.state.data?.pageParams || []

getNextPageParam / getPreviousPageParam / hasNextPage / hasPreviousPage simply didn't get the same defensive treatment. This PR makes them consistent.

Crash

TypeError: Cannot read properties of undefined (reading 'length')
  at getNextPageParam (infiniteQueryBehavior.ts) — const lastIndex = pages.length - 1
  at hasNextPage (infiniteQueryBehavior.ts)
  at InfiniteQueryObserver.createResult
  at InfiniteQueryObserver.updateResult
  ...

Seen in production on a TanStack Start (SSR) app across multiple infinite queries; intermittent, tied to hydration timing.

Change

  • Type the data argument of getNextPageParam / getPreviousPageParam as Partial<InfiniteData<unknown>> to reflect that it can be malformed at runtime (no as casts).
  • Guard if (!pages?.length) return undefined before indexing.
  • When pages is a valid non-empty array the behavior is unchanged — pageParams ?? [] is a no-op on well-formed data, since pages and pageParams are always written together.

The result: a malformed pages now yields "no next/previous page" instead of throwing, so hasNextPage / hasPreviousPage return false.

Test

Added a regression test asserting hasNextPage / hasPreviousPage return false (instead of throwing) for malformed InfiniteData. It fails without this change.

Changeset

Included as a patch for @tanstack/query-core.

Summary by CodeRabbit

  • Bug Fixes
    • Improved infinite query handling when stored data is incomplete or missing page information.
    • Prevented errors in “next” and “previous” page checks when page data is undefined, returning a safe result instead.
    • Added coverage for malformed infinite query data to ensure these checks behave reliably.

…iousPage

A malformed InfiniteData whose `pages` is undefined (e.g. from SSR hydration or setQueryData) reached getNextPageParam and threw "Cannot read properties of undefined (reading 'length')". Treat the data as Partial and guard before indexing, matching the existing state.data?.pages handling in onFetch.
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d11d64cb-deed-491b-9376-fbc9b374af17

📥 Commits

Reviewing files that changed from the base of the PR and between 8d979da and 0891b35.

📒 Files selected for processing (3)
  • .changeset/guard-infinite-undefined-pages.md
  • packages/query-core/src/__tests__/infiniteQueryBehavior.test.tsx
  • packages/query-core/src/infiniteQueryBehavior.ts

📝 Walkthrough

Walkthrough

Guards getNextPageParam and getPreviousPageParam in infiniteQueryBehavior.ts against malformed InfiniteData where pages is undefined, using optional chaining and a fallback empty array. A test verifies the helpers return false instead of throwing, and a changeset is added.

Changes

Infinite Query pages undefined guard

Layer / File(s) Summary
Core guard in getNextPageParam / getPreviousPageParam
packages/query-core/src/infiniteQueryBehavior.ts
Both helpers now destructure Partial<InfiniteData<unknown>>, guard with !pages?.length, and use pageParams ?? [] fallback, tolerating missing pages/pageParams.
Test and changeset
packages/query-core/src/__tests__/infiniteQueryBehavior.test.tsx, .changeset/guard-infinite-undefined-pages.md
Imports hasNextPage/hasPreviousPage in the test file; adds a test case asserting both return false for malformed InfiniteData; changeset records the patch.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~5 minutes

Poem

🐇 When pages are missing, oh what a fright,
The query would crash in the dark of the night.
But now with a guard and a ?. in place,
We return a calm false with infinite grace.
No TypeError thrown — just a hop and a skip! 🌙

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the change well, but it does not follow the required template and omits the checklist and release-impact sections. Reformat it to the repo template and add the Checklist and Release Impact sections, including the appropriate checked boxes.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: guarding hasNextPage/hasPreviousPage against undefined pages.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@ZacharyL2 ZacharyL2 marked this pull request as ready for review June 29, 2026 03:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant