Skip to content

fix(query-core): preserve mutation scope across option updates - #11531

Open
brennanbutler01 wants to merge 1 commit into
TanStack:mainfrom
brennanbutler01:fix/mutation-scope-queue
Open

brennanbutler01 wants to merge 1 commit into
TanStack:mainfrom
brennanbutler01:fix/mutation-scope-queue

Conversation

@brennanbutler01

@brennanbutler01 brennanbutler01 commented Sep 18, 2026

Copy link
Copy Markdown

🎯 Changes

Changing useMutation's scope while a mutation is running can leave other mutations in its original queue paused indefinitely. The cache indexes the mutation under its original scope, but settlement looks up the updated scope and never resumes the old queue. Removing the scope has the same effect.

Capture the scope when each mutation is created and retain it when options update. Other options still update, and future mutations use the observer's new scope. This also keeps cache removal aligned with the original scope.

Adds three core regressions covering changed/removed scopes, initially unscoped mutations, callback updates, and future mutations. Adds React coverage with and without Strict Mode. The new core regressions failed before the fix; all core and React tests now pass. A standalone public-API reproduction also passes against the built package.

Reproduced on 5.101.2, the 5.103.1 release source, and 66d4fe3. No matching issue or pull request was found; #11455 concerns callback reentrancy rather than queue membership.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested code changes locally with pnpm run test:pr, or these tests do not apply to this pull request.
  • I fully understand the code in this pull request, including any code generated with AI assistance.

The full cross-framework test:pr run was not performed. Both affected packages passed test:lib, test:types, test:eslint, and test:build through Nx, including dependency builds. The compiler matrix covers TypeScript 5.6, 5.7, 5.8, 5.9, 6.0, and 7.0. Existing lint warnings are in unchanged code. Tested on Node 24.13.0.

Implemented and locally verified with AI assistance. The contributor-understanding checkbox is left for the author's review.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • Bug Fixes
    • Mutation scopes now remain tied to the original mutation after observer options change.
    • Queued mutations correctly resume after an in-flight mutation settles, even when its observer scope changes.
    • Unscoped mutations remain unscoped when options are updated.
  • Tests
    • Added coverage for scope changes and queued mutation behavior in standard and Strict Mode.

Keep cache scope membership stable for each mutation so observer option
updates cannot strand other mutations in its original queue. Future
mutations still use the updated scope.

Cover changed, removed, and initially absent scopes in core tests, plus
React rerenders with and without Strict Mode.
@coderabbitai

coderabbitai Bot commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: bd5e15c1-b142-4341-aebd-1aab7247a3e4

📥 Commits

Reviewing files that changed from the base of the PR and between bb9d313 and 8102467.

📒 Files selected for processing (4)
  • .changeset/fix-mutation-scope-queue.md
  • packages/query-core/src/__tests__/mutationObserver.test.tsx
  • packages/query-core/src/mutation.ts
  • packages/react-query/src/__tests__/useMutation.test.tsx

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The change preserves each mutation’s initial scope when observer options change. Queued mutations continue under the original scope, while new mutations use updated options. Query-core and React tests cover scoped, unscoped, and StrictMode cases.

Changes

Mutation scope preservation

Layer / File(s) Summary
Preserve mutation creation scope
packages/query-core/src/mutation.ts, .changeset/fix-mutation-scope-queue.md
Mutation stores its initial scope and retains it in setOptions. The changeset documents the behavior.
Validate queued mutation behavior
packages/query-core/src/__tests__/mutationObserver.test.tsx, packages/react-query/src/__tests__/useMutation.test.tsx
Tests verify queued mutations resume after scope changes, running mutations retain their original scope, unscoped mutations remain unscoped, and behavior works with StrictMode.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: sukvvon

Merge Risk: ⚪ Minimal · up to 81024

The scope-preservation change is covered across the core and React mutation paths, with no actionable current-head risk identified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 3 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly and concisely describes the main change: preserving mutation scope across option updates.
Description check ✅ Passed The description follows the repository template, explains the problem and solution, documents testing and release impact, and includes the required changeset. It also clearly notes that the full test:…
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 3 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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.

@brennanbutler01
brennanbutler01 marked this pull request as ready for review September 18, 2026 03:55
Copilot AI lite review requested due to automatic review settings September 18, 2026 03:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The scope fix and supporting core and React regressions are fully covered with no unresolved blocking issues.

Pull request overview

Preserves each mutation’s original scope across option updates, preventing queued mutations from remaining paused.

Changes:

  • Retains mutation scope at creation.
  • Adds core and React regression coverage.
  • Adds a patch changeset.
File summaries
File Description
packages/react-query/src/__tests__/useMutation.test.tsx Tests React scope updates with and without Strict Mode.
packages/query-core/src/mutation.ts Preserves the original mutation scope.
packages/query-core/src/__tests__/mutationObserver.test.tsx Tests scope retention and future mutations.
.changeset/fix-mutation-scope-queue.md Documents the patch release.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

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.

3 participants