Skip to content

fix(query-core): keep nested mutate callbacks scoped to the settling mutation 🤖🤖🤖 - #11455

Open
rome-xi wants to merge 1 commit into
TanStack:mainfrom
rome-xi:contrib/tanstack-query-11451
Open

fix(query-core): keep nested mutate callbacks scoped to the settling mutation 🤖🤖🤖#11455
rome-xi wants to merge 1 commit into
TanStack:mainfrom
rome-xi:contrib/tanstack-query-11451

Conversation

@rome-xi

@rome-xi rome-xi commented Sep 9, 2026

Copy link
Copy Markdown

🎯 Changes

MutationObserver.#notify invoked per-call onSettled from the live this.#mutateOptions after onSuccess/onError. If those callbacks start another mutate() on the same observer, they overwrite #mutateOptions before onSettled runs. The inner callback then receives the outer mutation's data/variables, the outer onSettled never fires, and a nested mutate() with no options throws TypeError: Cannot read properties of undefined (reading 'onSettled').

Capture the per-call options for the mutation that is settling (result fields were already snapshotted) and invoke callbacks from that snapshot.

Fixes #11451

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested code changes locally with pnpm nx run @tanstack/query-core:test:lib -- mutationObserver.test and pnpm nx run @tanstack/react-query:test:lib -- useMutation.test.
  • I fully understand the code in this pull request, including any code generated with AI assistance.

🚀 Release Impact

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

An AI coding assistant helped draft the regression tests and the #notify snapshot. I reproduced the bug on current main, confirmed the new tests fail for the missing outer onSettled / TypeError, and confirmed they pass after the snapshot.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed nested mutation handling so each mutation’s onSettled callback receives the correct result, error, variables, and context.
    • Prevented inner mutation activity from overwriting callbacks or settlement data for an ongoing outer mutation.
    • Prevented unhandled promise rejections when triggering nested mutations without callback options.
  • Tests

    • Added coverage for nested mutations initiated from success and error callbacks.

…mutation

Signed-off-by: rome-xi <rome-xi@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Sep 9, 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: 361804f4-86f8-4020-9bd8-08158b70fde8

📥 Commits

Reviewing files that changed from the base of the PR and between f7c6be3 and 0ef087e.

📒 Files selected for processing (4)
  • .changeset/nested-mutate-onsettled.md
  • packages/query-core/src/__tests__/mutationObserver.test.tsx
  • packages/query-core/src/mutationObserver.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 mutation observer now snapshots per-call callback options and settlement data before callbacks can start nested mutations. Core and React tests cover nested success and error flows, pending mutations, mutation context, and omitted options.

Changes

Nested mutation settlement callbacks

Layer / File(s) Summary
Snapshot settlement callbacks
packages/query-core/src/mutationObserver.ts
#notify uses a local per-call options snapshot for success, error, and settlement callbacks.
Nested mutation regression coverage
packages/query-core/src/__tests__/mutationObserver.test.tsx, packages/react-query/src/__tests__/useMutation.test.tsx, .changeset/nested-mutate-onsettled.md
Tests verify that nested mutations retain their own results, errors, variables, pending state, and mutation context. The changeset declares a patch release for @tanstack/query-core.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 0ef08

Nested mutation callbacks now retain their own result, error, variables, and context, preventing cross-mutation callback payloads and omitted-options failures. The change is ready to merge.

Suggested reviewers: sukvvon

🚥 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 3 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
Title check ✅ Passed The title clearly identifies the query-core fix and the affected nested mutate callbacks. The emojis are unnecessary but do not obscure the change.
Description check ✅ Passed The description is complete. It explains the bug, fix, linked issue, testing, checklist status, release impact, and AI assistance.
Linked Issues check ✅ Passed The implementation addresses issue #11451 by snapshotting per-call options, preserving the settling mutation's data, error, and variables, preventing duplicate or missing onSettled calls, and avoiding…
Out of Scope Changes check ✅ Passed The source change, regression tests, and changeset directly support the linked issue and stated objectives. No unrelated code changes are identified.
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 3 functions across 3 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ 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.

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.

useMutation invokes the next mutation's onSettled with the previous result

1 participant