Skip to content

fix(query-core): handle combine throwing in QueriesObserver notify#10137

Open
veeceey wants to merge 2 commits intoTanStack:mainfrom
veeceey:fix/issue-10129-suspense-queries-combine
Open

fix(query-core): handle combine throwing in QueriesObserver notify#10137
veeceey wants to merge 2 commits intoTanStack:mainfrom
veeceey:fix/issue-10129-suspense-queries-combine

Conversation

@veeceey
Copy link

@veeceey veeceey commented Feb 15, 2026

Fixes #10129

When useSuspenseQueries is used with combine, the types narrow data to always be defined. But if a query transitions back to pending/error state (e.g. via queryClient.resetQueries()), the combine function gets called with results where data is undefined, causing a runtime TypeError.

This happens because QueriesObserver.#notify() calls combine as an optimization check — to see if the combined result changed before notifying listeners. The listeners themselves receive raw results (not the combined one), so the combine call is purely for deduplication.

The fix wraps the combine call in a try/catch. If combine throws, we treat it as a change and notify listeners anyway. This lets the framework-level code (React Suspense / Error Boundary) handle the state transition properly.

Added a test that reproduces the exact scenario: subscribe to a QueriesObserver with a combine function that accesses data properties, let queries resolve, then call resetQueries — previously this would throw, now it correctly notifies listeners with the pending result.

Summary by CodeRabbit

  • Bug Fixes

    • Improved observation notification so listeners are reliably notified even if a data-combining step throws.
  • Tests

    • Added test coverage for notification behavior during query resets and error scenarios (duplicate test entry present).
  • Chores

    • Added a changeset documenting the fix and bumping the patch version.

@changeset-bot
Copy link

changeset-bot bot commented Feb 15, 2026

🦋 Changeset detected

Latest commit: 2caed00

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

This PR includes changesets to release 22 packages
Name Type
@tanstack/query-core Patch
@tanstack/angular-query-experimental Patch
@tanstack/preact-query 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/preact-query-devtools Patch
@tanstack/preact-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 Feb 15, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b904770c-fc04-481b-b748-7561513185c8

📥 Commits

Reviewing files that changed from the base of the PR and between ab3e122 and 2caed00.

📒 Files selected for processing (3)
  • .changeset/brave-tigers-wave.md
  • packages/query-core/src/__tests__/queriesObserver.test.tsx
  • packages/query-core/src/queriesObserver.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/query-core/src/queriesObserver.ts

📝 Walkthrough

Walkthrough

Adds guarded notification logic to QueriesObserver.notify so combine() errors don't prevent listener notifications. Includes a test asserting listeners are notified with pending status and undefined data when combine throws after a query reset, and a changeset recording the fix.

Changes

Cohort / File(s) Summary
Core Implementation
packages/query-core/src/queriesObserver.ts
Wraps the combine/newResult computation in a try/catch, introduces a shouldNotify fallback when combine throws, and preserves tracking and result update flow so listeners are still notified even if combine errors.
Test Coverage
packages/query-core/src/__tests__/queriesObserver.test.tsx
Adds a test "should still notify listeners when combine throws after query reset" that verifies a listener receives a pending status with undefined data after a reset that causes combine to throw.
Release Metadata
.changeset/brave-tigers-wave.md
Adds a changeset patch noting the fix: "handle combine throwing in QueriesObserver notify".

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Subscriber
participant QueriesObserver
participant QuerySet
Subscriber->>QueriesObserver: subscribe()
QueriesObserver->>QuerySet: read latest query results
QuerySet-->>QueriesObserver: results (may include pending/error)
alt combine succeeds
QueriesObserver->>QueriesObserver: compute newResult = combine(results)
QueriesObserver->>Subscriber: notify(newResult)
else combine throws
QueriesObserver->>QueriesObserver: catch error
QueriesObserver->>Subscriber: notify(fallback pending/undefined result)
end

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • TkDodo

Poem

🐰 I stitched a gentle, watchful thread,
So falls from combine won't cloud what's said.
Listeners still prick their eager ears,
Even when queries stall with fears.
Hoppity hops — error handled, cheer! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(query-core): handle combine throwing in QueriesObserver notify' accurately and concisely summarizes the main fix in the changeset.
Description check ✅ Passed The PR description clearly explains the problem, fix, rationale, and testing approach. The checklist template was provided but completion status is not required for this assessment.
Linked Issues check ✅ Passed The changes successfully address #10129 by wrapping the combine call in a try/catch block, allowing listeners to be notified even when combine throws, which handles pending/error state transitions.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the reported issue: error handling in QueriesObserver.notify, a corresponding test, and a changeset entry.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

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

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.

veeceey added 2 commits March 10, 2026 06:14
When useSuspenseQueries is used with combine and a query transitions
to pending/error state (e.g. after resetQueries), the combine function
throws because data is undefined despite types narrowing it as defined.

The #notify method calls combine as an optimization to check if the
combined result changed. If combine throws during this check, we now
catch the error and still notify listeners so the framework can
re-suspend or show an error boundary.

Fixes TanStack#10129
@veeceey veeceey force-pushed the fix/issue-10129-suspense-queries-combine branch from 8c6c7ad to 2caed00 Compare March 10, 2026 13:15
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.

useSuspenseQueries combine is called with pending/error results despite types implying data is always defined

1 participant