fix(solid-query): scope useMutation's cache subscription to the flight - #11325

Merged
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription
Aug 29, 2026
Merged

fix(solid-query): scope useMutation's cache subscription to the flight#11325
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription

Conversation

@ryansolid

Copy link
Copy Markdown

Summary

Alternative to #11324 — thanks @brenelz for catching the STRICT_READ_UNTRACKED diagnostic. Rather than untracking the mount-time client() read, this removes it: the diagnostic was pointing at a subscription that shouldn't exist at mount at all.

useMutation subscribed to the mutation cache at setup and held that subscription for the hook's whole life, but the listener only does anything between mutate and settle (activeMutation is null otherwise). The subscription now starts inside run, created against the same client the mutation is built on, and ends at the settle points (plus onCleanup for unmount mid-flight; a rapid re-mutate replaces the previous flight's listener).

What this buys over untrack:

  • Nothing reactive is read in the component body — the diagnostic goes away because the read is gone, not declared intentional.
  • Listener and mutation share a client by construction. Previously the subscription snapshotted the mount-time client while mutate built against the live one — a QueryClient swap could leave the listener on the old cache, silently dropping flight events.
  • Idle hooks hold no subscription. Every mounted useMutation used to hear every mutation-cache event forever just to filter it out; now cache events only fan out to hooks actually in flight.

Tests

Made with Cursor

The hook subscribed to the mutation cache at mount with a bare reactive
client() read — tripping Solid's STRICT_READ_UNTRACKED dev diagnostic
(reported by @brenelz in TanStack#11324) — and held that subscription for its
whole life even though the listener only matters between mutate and
settle. Rather than untracking the read, remove it: subscribe inside
run(), against the same client the mutation is built on, and unsubscribe
at the settle points (plus onCleanup for unmount mid-flight).
By construction: no reactive read at setup (nothing to untrack), the
listener and the mutation can never sit on different clients across a
QueryClient swap, and an idle useMutation holds no cache subscription —
mutation-cache events no longer fan out to every mounted hook.
Includes the TanStack#11324 regression test (no strict-read diagnostic on mount)
plus a listener-count test pinning the idle/flight/settled subscription
lifecycle.
Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b08366f7-a91d-4435-ad54-3037604deef8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@nx-cloud

nx-cloudBot commented Aug 29, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit afe2bf1

CommandStatusDurationResult
nx affected --targets=test:sherif,test:knip,tes...✅ Succeeded4m 25sView ↗
nx run-many --target=build --exclude=examples/*...✅ Succeeded17sView ↗

☁️ Nx Cloud last updated this comment at 2026-08-29 19:24:58 UTC

@pkg-pr-new

Copy link
Copy Markdown
More templates

@tanstack/angular-query-experimental

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

@tanstack/eslint-plugin-query

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

@tanstack/lit-query

npm i https://pkg.pr.new/@tanstack/lit-query@11325

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@11325

@tanstack/preact-query-devtools

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

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@11325

@tanstack/query-async-storage-persister

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

@tanstack/query-broadcast-client-experimental

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

@tanstack/query-core

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

@tanstack/query-devtools

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

@tanstack/query-persist-client-core

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

@tanstack/query-sync-storage-persister

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

@tanstack/react-query

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

@tanstack/react-query-devtools

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

@tanstack/react-query-next-experimental

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

@tanstack/react-query-persist-client

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

@tanstack/solid-query

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

@tanstack/solid-query-devtools

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

@tanstack/solid-query-persist-client

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

@tanstack/svelte-query

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

@tanstack/svelte-query-devtools

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

@tanstack/svelte-query-persist-client

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

@tanstack/vue-query

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

@tanstack/vue-query-devtools

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

commit: afe2bf1

@brenelz
brenelz merged commit 209f9f5 into TanStack:solid-query-v6-preAug 29, 2026
9 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 29, 2026
Sign up for freeto 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.

2 participants

@ryansolid@brenelz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(solid-query): scope useMutation's cache subscription to the flight - #11325

Merged
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription
Aug 29, 2026
Merged

fix(solid-query): scope useMutation's cache subscription to the flight#11325
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription

Conversation

@ryansolid

Copy link
Copy Markdown

Summary

Alternative to #11324 — thanks @brenelz for catching the STRICT_READ_UNTRACKED diagnostic. Rather than untracking the mount-time client() read, this removes it: the diagnostic was pointing at a subscription that shouldn't exist at mount at all.

useMutation subscribed to the mutation cache at setup and held that subscription for the hook's whole life, but the listener only does anything between mutate and settle (activeMutation is null otherwise). The subscription now starts inside run, created against the same client the mutation is built on, and ends at the settle points (plus onCleanup for unmount mid-flight; a rapid re-mutate replaces the previous flight's listener).

What this buys over untrack:

  • Nothing reactive is read in the component body — the diagnostic goes away because the read is gone, not declared intentional.
  • Listener and mutation share a client by construction. Previously the subscription snapshotted the mount-time client while mutate built against the live one — a QueryClient swap could leave the listener on the old cache, silently dropping flight events.
  • Idle hooks hold no subscription. Every mounted useMutation used to hear every mutation-cache event forever just to filter it out; now cache events only fan out to hooks actually in flight.

Tests

Made with Cursor

The hook subscribed to the mutation cache at mount with a bare reactive
client() read — tripping Solid's STRICT_READ_UNTRACKED dev diagnostic
(reported by @brenelz in TanStack#11324) — and held that subscription for its
whole life even though the listener only matters between mutate and
settle. Rather than untracking the read, remove it: subscribe inside
run(), against the same client the mutation is built on, and unsubscribe
at the settle points (plus onCleanup for unmount mid-flight).
By construction: no reactive read at setup (nothing to untrack), the
listener and the mutation can never sit on different clients across a
QueryClient swap, and an idle useMutation holds no cache subscription —
mutation-cache events no longer fan out to every mounted hook.
Includes the TanStack#11324 regression test (no strict-read diagnostic on mount)
plus a listener-count test pinning the idle/flight/settled subscription
lifecycle.
Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b08366f7-a91d-4435-ad54-3037604deef8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@nx-cloud

nx-cloudBot commented Aug 29, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit afe2bf1

CommandStatusDurationResult
nx affected --targets=test:sherif,test:knip,tes...✅ Succeeded4m 25sView ↗
nx run-many --target=build --exclude=examples/*...✅ Succeeded17sView ↗

☁️ Nx Cloud last updated this comment at 2026-08-29 19:24:58 UTC

@pkg-pr-new

Copy link
Copy Markdown
More templates

@tanstack/angular-query-experimental

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

@tanstack/eslint-plugin-query

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

@tanstack/lit-query

npm i https://pkg.pr.new/@tanstack/lit-query@11325

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@11325

@tanstack/preact-query-devtools

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

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@11325

@tanstack/query-async-storage-persister

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

@tanstack/query-broadcast-client-experimental

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

@tanstack/query-core

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

@tanstack/query-devtools

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

@tanstack/query-persist-client-core

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

@tanstack/query-sync-storage-persister

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

@tanstack/react-query

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

@tanstack/react-query-devtools

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

@tanstack/react-query-next-experimental

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

@tanstack/react-query-persist-client

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

@tanstack/solid-query

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

@tanstack/solid-query-devtools

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

@tanstack/solid-query-persist-client

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

@tanstack/svelte-query

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

@tanstack/svelte-query-devtools

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

@tanstack/svelte-query-persist-client

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

@tanstack/vue-query

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

@tanstack/vue-query-devtools

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

commit: afe2bf1

@brenelz
brenelz merged commit 209f9f5 into TanStack:solid-query-v6-preAug 29, 2026
9 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 29, 2026
Sign up for freeto 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.

2 participants

@ryansolid@brenelz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(solid-query): scope useMutation's cache subscription to the flight - #11325

Merged
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription
Aug 29, 2026
Merged

fix(solid-query): scope useMutation's cache subscription to the flight#11325
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription

Conversation

@ryansolid

Copy link
Copy Markdown

Summary

Alternative to #11324 — thanks @brenelz for catching the STRICT_READ_UNTRACKED diagnostic. Rather than untracking the mount-time client() read, this removes it: the diagnostic was pointing at a subscription that shouldn't exist at mount at all.

useMutation subscribed to the mutation cache at setup and held that subscription for the hook's whole life, but the listener only does anything between mutate and settle (activeMutation is null otherwise). The subscription now starts inside run, created against the same client the mutation is built on, and ends at the settle points (plus onCleanup for unmount mid-flight; a rapid re-mutate replaces the previous flight's listener).

What this buys over untrack:

  • Nothing reactive is read in the component body — the diagnostic goes away because the read is gone, not declared intentional.
  • Listener and mutation share a client by construction. Previously the subscription snapshotted the mount-time client while mutate built against the live one — a QueryClient swap could leave the listener on the old cache, silently dropping flight events.
  • Idle hooks hold no subscription. Every mounted useMutation used to hear every mutation-cache event forever just to filter it out; now cache events only fan out to hooks actually in flight.

Tests

Made with Cursor

The hook subscribed to the mutation cache at mount with a bare reactive
client() read — tripping Solid's STRICT_READ_UNTRACKED dev diagnostic
(reported by @brenelz in TanStack#11324) — and held that subscription for its
whole life even though the listener only matters between mutate and
settle. Rather than untracking the read, remove it: subscribe inside
run(), against the same client the mutation is built on, and unsubscribe
at the settle points (plus onCleanup for unmount mid-flight).
By construction: no reactive read at setup (nothing to untrack), the
listener and the mutation can never sit on different clients across a
QueryClient swap, and an idle useMutation holds no cache subscription —
mutation-cache events no longer fan out to every mounted hook.
Includes the TanStack#11324 regression test (no strict-read diagnostic on mount)
plus a listener-count test pinning the idle/flight/settled subscription
lifecycle.
Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b08366f7-a91d-4435-ad54-3037604deef8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@nx-cloud

nx-cloudBot commented Aug 29, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit afe2bf1

CommandStatusDurationResult
nx affected --targets=test:sherif,test:knip,tes...✅ Succeeded4m 25sView ↗
nx run-many --target=build --exclude=examples/*...✅ Succeeded17sView ↗

☁️ Nx Cloud last updated this comment at 2026-08-29 19:24:58 UTC

@pkg-pr-new

Copy link
Copy Markdown
More templates

@tanstack/angular-query-experimental

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

@tanstack/eslint-plugin-query

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

@tanstack/lit-query

npm i https://pkg.pr.new/@tanstack/lit-query@11325

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@11325

@tanstack/preact-query-devtools

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

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@11325

@tanstack/query-async-storage-persister

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

@tanstack/query-broadcast-client-experimental

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

@tanstack/query-core

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

@tanstack/query-devtools

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

@tanstack/query-persist-client-core

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

@tanstack/query-sync-storage-persister

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

@tanstack/react-query

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

@tanstack/react-query-devtools

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

@tanstack/react-query-next-experimental

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

@tanstack/react-query-persist-client

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

@tanstack/solid-query

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

@tanstack/solid-query-devtools

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

@tanstack/solid-query-persist-client

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

@tanstack/svelte-query

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

@tanstack/svelte-query-devtools

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

@tanstack/svelte-query-persist-client

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

@tanstack/vue-query

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

@tanstack/vue-query-devtools

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

commit: afe2bf1

@brenelz
brenelz merged commit 209f9f5 into TanStack:solid-query-v6-preAug 29, 2026
9 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 29, 2026
Sign up for freeto 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.

2 participants

@ryansolid@brenelz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(solid-query): scope useMutation's cache subscription to the flight - #11325

Merged
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription
Aug 29, 2026
Merged

fix(solid-query): scope useMutation's cache subscription to the flight#11325
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription

Conversation

@ryansolid

Copy link
Copy Markdown

Summary

Alternative to #11324 — thanks @brenelz for catching the STRICT_READ_UNTRACKED diagnostic. Rather than untracking the mount-time client() read, this removes it: the diagnostic was pointing at a subscription that shouldn't exist at mount at all.

useMutation subscribed to the mutation cache at setup and held that subscription for the hook's whole life, but the listener only does anything between mutate and settle (activeMutation is null otherwise). The subscription now starts inside run, created against the same client the mutation is built on, and ends at the settle points (plus onCleanup for unmount mid-flight; a rapid re-mutate replaces the previous flight's listener).

What this buys over untrack:

  • Nothing reactive is read in the component body — the diagnostic goes away because the read is gone, not declared intentional.
  • Listener and mutation share a client by construction. Previously the subscription snapshotted the mount-time client while mutate built against the live one — a QueryClient swap could leave the listener on the old cache, silently dropping flight events.
  • Idle hooks hold no subscription. Every mounted useMutation used to hear every mutation-cache event forever just to filter it out; now cache events only fan out to hooks actually in flight.

Tests

Made with Cursor

The hook subscribed to the mutation cache at mount with a bare reactive
client() read — tripping Solid's STRICT_READ_UNTRACKED dev diagnostic
(reported by @brenelz in TanStack#11324) — and held that subscription for its
whole life even though the listener only matters between mutate and
settle. Rather than untracking the read, remove it: subscribe inside
run(), against the same client the mutation is built on, and unsubscribe
at the settle points (plus onCleanup for unmount mid-flight).
By construction: no reactive read at setup (nothing to untrack), the
listener and the mutation can never sit on different clients across a
QueryClient swap, and an idle useMutation holds no cache subscription —
mutation-cache events no longer fan out to every mounted hook.
Includes the TanStack#11324 regression test (no strict-read diagnostic on mount)
plus a listener-count test pinning the idle/flight/settled subscription
lifecycle.
Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b08366f7-a91d-4435-ad54-3037604deef8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@nx-cloud

nx-cloudBot commented Aug 29, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit afe2bf1

CommandStatusDurationResult
nx affected --targets=test:sherif,test:knip,tes...✅ Succeeded4m 25sView ↗
nx run-many --target=build --exclude=examples/*...✅ Succeeded17sView ↗

☁️ Nx Cloud last updated this comment at 2026-08-29 19:24:58 UTC

@pkg-pr-new

Copy link
Copy Markdown
More templates

@tanstack/angular-query-experimental

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

@tanstack/eslint-plugin-query

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

@tanstack/lit-query

npm i https://pkg.pr.new/@tanstack/lit-query@11325

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@11325

@tanstack/preact-query-devtools

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

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@11325

@tanstack/query-async-storage-persister

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

@tanstack/query-broadcast-client-experimental

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

@tanstack/query-core

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

@tanstack/query-devtools

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

@tanstack/query-persist-client-core

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

@tanstack/query-sync-storage-persister

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

@tanstack/react-query

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

@tanstack/react-query-devtools

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

@tanstack/react-query-next-experimental

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

@tanstack/react-query-persist-client

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

@tanstack/solid-query

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

@tanstack/solid-query-devtools

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

@tanstack/solid-query-persist-client

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

@tanstack/svelte-query

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

@tanstack/svelte-query-devtools

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

@tanstack/svelte-query-persist-client

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

@tanstack/vue-query

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

@tanstack/vue-query-devtools

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

commit: afe2bf1

@brenelz
brenelz merged commit 209f9f5 into TanStack:solid-query-v6-preAug 29, 2026
9 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 29, 2026
Sign up for freeto 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.

2 participants

@ryansolid@brenelz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(solid-query): scope useMutation's cache subscription to the flight - #11325

Merged
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription
Aug 29, 2026
Merged

fix(solid-query): scope useMutation's cache subscription to the flight#11325
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription

Conversation

@ryansolid

Copy link
Copy Markdown

Summary

Alternative to #11324 — thanks @brenelz for catching the STRICT_READ_UNTRACKED diagnostic. Rather than untracking the mount-time client() read, this removes it: the diagnostic was pointing at a subscription that shouldn't exist at mount at all.

useMutation subscribed to the mutation cache at setup and held that subscription for the hook's whole life, but the listener only does anything between mutate and settle (activeMutation is null otherwise). The subscription now starts inside run, created against the same client the mutation is built on, and ends at the settle points (plus onCleanup for unmount mid-flight; a rapid re-mutate replaces the previous flight's listener).

What this buys over untrack:

  • Nothing reactive is read in the component body — the diagnostic goes away because the read is gone, not declared intentional.
  • Listener and mutation share a client by construction. Previously the subscription snapshotted the mount-time client while mutate built against the live one — a QueryClient swap could leave the listener on the old cache, silently dropping flight events.
  • Idle hooks hold no subscription. Every mounted useMutation used to hear every mutation-cache event forever just to filter it out; now cache events only fan out to hooks actually in flight.

Tests

Made with Cursor

The hook subscribed to the mutation cache at mount with a bare reactive
client() read — tripping Solid's STRICT_READ_UNTRACKED dev diagnostic
(reported by @brenelz in TanStack#11324) — and held that subscription for its
whole life even though the listener only matters between mutate and
settle. Rather than untracking the read, remove it: subscribe inside
run(), against the same client the mutation is built on, and unsubscribe
at the settle points (plus onCleanup for unmount mid-flight).
By construction: no reactive read at setup (nothing to untrack), the
listener and the mutation can never sit on different clients across a
QueryClient swap, and an idle useMutation holds no cache subscription —
mutation-cache events no longer fan out to every mounted hook.
Includes the TanStack#11324 regression test (no strict-read diagnostic on mount)
plus a listener-count test pinning the idle/flight/settled subscription
lifecycle.
Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b08366f7-a91d-4435-ad54-3037604deef8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@nx-cloud

nx-cloudBot commented Aug 29, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit afe2bf1

CommandStatusDurationResult
nx affected --targets=test:sherif,test:knip,tes...✅ Succeeded4m 25sView ↗
nx run-many --target=build --exclude=examples/*...✅ Succeeded17sView ↗

☁️ Nx Cloud last updated this comment at 2026-08-29 19:24:58 UTC

@pkg-pr-new

Copy link
Copy Markdown
More templates

@tanstack/angular-query-experimental

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

@tanstack/eslint-plugin-query

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

@tanstack/lit-query

npm i https://pkg.pr.new/@tanstack/lit-query@11325

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@11325

@tanstack/preact-query-devtools

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

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@11325

@tanstack/query-async-storage-persister

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

@tanstack/query-broadcast-client-experimental

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

@tanstack/query-core

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

@tanstack/query-devtools

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

@tanstack/query-persist-client-core

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

@tanstack/query-sync-storage-persister

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

@tanstack/react-query

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

@tanstack/react-query-devtools

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

@tanstack/react-query-next-experimental

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

@tanstack/react-query-persist-client

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

@tanstack/solid-query

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

@tanstack/solid-query-devtools

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

@tanstack/solid-query-persist-client

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

@tanstack/svelte-query

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

@tanstack/svelte-query-devtools

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

@tanstack/svelte-query-persist-client

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

@tanstack/vue-query

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

@tanstack/vue-query-devtools

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

commit: afe2bf1

@brenelz
brenelz merged commit 209f9f5 into TanStack:solid-query-v6-preAug 29, 2026
9 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 29, 2026
Sign up for freeto 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.

2 participants

@ryansolid@brenelz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(solid-query): scope useMutation's cache subscription to the flight - #11325

Merged
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription
Aug 29, 2026
Merged

fix(solid-query): scope useMutation's cache subscription to the flight#11325
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription

Conversation

@ryansolid

Copy link
Copy Markdown

Summary

Alternative to #11324 — thanks @brenelz for catching the STRICT_READ_UNTRACKED diagnostic. Rather than untracking the mount-time client() read, this removes it: the diagnostic was pointing at a subscription that shouldn't exist at mount at all.

useMutation subscribed to the mutation cache at setup and held that subscription for the hook's whole life, but the listener only does anything between mutate and settle (activeMutation is null otherwise). The subscription now starts inside run, created against the same client the mutation is built on, and ends at the settle points (plus onCleanup for unmount mid-flight; a rapid re-mutate replaces the previous flight's listener).

What this buys over untrack:

  • Nothing reactive is read in the component body — the diagnostic goes away because the read is gone, not declared intentional.
  • Listener and mutation share a client by construction. Previously the subscription snapshotted the mount-time client while mutate built against the live one — a QueryClient swap could leave the listener on the old cache, silently dropping flight events.
  • Idle hooks hold no subscription. Every mounted useMutation used to hear every mutation-cache event forever just to filter it out; now cache events only fan out to hooks actually in flight.

Tests

Made with Cursor

The hook subscribed to the mutation cache at mount with a bare reactive
client() read — tripping Solid's STRICT_READ_UNTRACKED dev diagnostic
(reported by @brenelz in TanStack#11324) — and held that subscription for its
whole life even though the listener only matters between mutate and
settle. Rather than untracking the read, remove it: subscribe inside
run(), against the same client the mutation is built on, and unsubscribe
at the settle points (plus onCleanup for unmount mid-flight).
By construction: no reactive read at setup (nothing to untrack), the
listener and the mutation can never sit on different clients across a
QueryClient swap, and an idle useMutation holds no cache subscription —
mutation-cache events no longer fan out to every mounted hook.
Includes the TanStack#11324 regression test (no strict-read diagnostic on mount)
plus a listener-count test pinning the idle/flight/settled subscription
lifecycle.
Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b08366f7-a91d-4435-ad54-3037604deef8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@nx-cloud

nx-cloudBot commented Aug 29, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit afe2bf1

CommandStatusDurationResult
nx affected --targets=test:sherif,test:knip,tes...✅ Succeeded4m 25sView ↗
nx run-many --target=build --exclude=examples/*...✅ Succeeded17sView ↗

☁️ Nx Cloud last updated this comment at 2026-08-29 19:24:58 UTC

@pkg-pr-new

Copy link
Copy Markdown
More templates

@tanstack/angular-query-experimental

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

@tanstack/eslint-plugin-query

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

@tanstack/lit-query

npm i https://pkg.pr.new/@tanstack/lit-query@11325

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@11325

@tanstack/preact-query-devtools

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

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@11325

@tanstack/query-async-storage-persister

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

@tanstack/query-broadcast-client-experimental

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

@tanstack/query-core

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

@tanstack/query-devtools

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

@tanstack/query-persist-client-core

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

@tanstack/query-sync-storage-persister

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

@tanstack/react-query

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

@tanstack/react-query-devtools

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

@tanstack/react-query-next-experimental

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

@tanstack/react-query-persist-client

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

@tanstack/solid-query

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

@tanstack/solid-query-devtools

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

@tanstack/solid-query-persist-client

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

@tanstack/svelte-query

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

@tanstack/svelte-query-devtools

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

@tanstack/svelte-query-persist-client

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

@tanstack/vue-query

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

@tanstack/vue-query-devtools

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

commit: afe2bf1

@brenelz
brenelz merged commit 209f9f5 into TanStack:solid-query-v6-preAug 29, 2026
9 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 29, 2026
Sign up for freeto 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.

2 participants

@ryansolid@brenelz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(solid-query): scope useMutation's cache subscription to the flight - #11325

Merged
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription
Aug 29, 2026
Merged

fix(solid-query): scope useMutation's cache subscription to the flight#11325
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription

Conversation

@ryansolid

Copy link
Copy Markdown

Summary

Alternative to #11324 — thanks @brenelz for catching the STRICT_READ_UNTRACKED diagnostic. Rather than untracking the mount-time client() read, this removes it: the diagnostic was pointing at a subscription that shouldn't exist at mount at all.

useMutation subscribed to the mutation cache at setup and held that subscription for the hook's whole life, but the listener only does anything between mutate and settle (activeMutation is null otherwise). The subscription now starts inside run, created against the same client the mutation is built on, and ends at the settle points (plus onCleanup for unmount mid-flight; a rapid re-mutate replaces the previous flight's listener).

What this buys over untrack:

  • Nothing reactive is read in the component body — the diagnostic goes away because the read is gone, not declared intentional.
  • Listener and mutation share a client by construction. Previously the subscription snapshotted the mount-time client while mutate built against the live one — a QueryClient swap could leave the listener on the old cache, silently dropping flight events.
  • Idle hooks hold no subscription. Every mounted useMutation used to hear every mutation-cache event forever just to filter it out; now cache events only fan out to hooks actually in flight.

Tests

Made with Cursor

The hook subscribed to the mutation cache at mount with a bare reactive
client() read — tripping Solid's STRICT_READ_UNTRACKED dev diagnostic
(reported by @brenelz in TanStack#11324) — and held that subscription for its
whole life even though the listener only matters between mutate and
settle. Rather than untracking the read, remove it: subscribe inside
run(), against the same client the mutation is built on, and unsubscribe
at the settle points (plus onCleanup for unmount mid-flight).
By construction: no reactive read at setup (nothing to untrack), the
listener and the mutation can never sit on different clients across a
QueryClient swap, and an idle useMutation holds no cache subscription —
mutation-cache events no longer fan out to every mounted hook.
Includes the TanStack#11324 regression test (no strict-read diagnostic on mount)
plus a listener-count test pinning the idle/flight/settled subscription
lifecycle.
Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b08366f7-a91d-4435-ad54-3037604deef8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@nx-cloud

nx-cloudBot commented Aug 29, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit afe2bf1

CommandStatusDurationResult
nx affected --targets=test:sherif,test:knip,tes...✅ Succeeded4m 25sView ↗
nx run-many --target=build --exclude=examples/*...✅ Succeeded17sView ↗

☁️ Nx Cloud last updated this comment at 2026-08-29 19:24:58 UTC

@pkg-pr-new

Copy link
Copy Markdown
More templates

@tanstack/angular-query-experimental

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

@tanstack/eslint-plugin-query

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

@tanstack/lit-query

npm i https://pkg.pr.new/@tanstack/lit-query@11325

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@11325

@tanstack/preact-query-devtools

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

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@11325

@tanstack/query-async-storage-persister

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

@tanstack/query-broadcast-client-experimental

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

@tanstack/query-core

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

@tanstack/query-devtools

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

@tanstack/query-persist-client-core

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

@tanstack/query-sync-storage-persister

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

@tanstack/react-query

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

@tanstack/react-query-devtools

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

@tanstack/react-query-next-experimental

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

@tanstack/react-query-persist-client

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

@tanstack/solid-query

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

@tanstack/solid-query-devtools

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

@tanstack/solid-query-persist-client

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

@tanstack/svelte-query

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

@tanstack/svelte-query-devtools

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

@tanstack/svelte-query-persist-client

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

@tanstack/vue-query

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

@tanstack/vue-query-devtools

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

commit: afe2bf1

@brenelz
brenelz merged commit 209f9f5 into TanStack:solid-query-v6-preAug 29, 2026
9 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 29, 2026
Sign up for freeto 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.

2 participants

@ryansolid@brenelz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(solid-query): scope useMutation's cache subscription to the flight - #11325

Merged
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription
Aug 29, 2026
Merged

fix(solid-query): scope useMutation's cache subscription to the flight#11325
brenelz merged 1 commit into
TanStack:solid-query-v6-prefrom
ryansolid:refactor/mutation-flight-subscription

Conversation

@ryansolid

Copy link
Copy Markdown

Summary

Alternative to #11324 — thanks @brenelz for catching the STRICT_READ_UNTRACKED diagnostic. Rather than untracking the mount-time client() read, this removes it: the diagnostic was pointing at a subscription that shouldn't exist at mount at all.

useMutation subscribed to the mutation cache at setup and held that subscription for the hook's whole life, but the listener only does anything between mutate and settle (activeMutation is null otherwise). The subscription now starts inside run, created against the same client the mutation is built on, and ends at the settle points (plus onCleanup for unmount mid-flight; a rapid re-mutate replaces the previous flight's listener).

What this buys over untrack:

  • Nothing reactive is read in the component body — the diagnostic goes away because the read is gone, not declared intentional.
  • Listener and mutation share a client by construction. Previously the subscription snapshotted the mount-time client while mutate built against the live one — a QueryClient swap could leave the listener on the old cache, silently dropping flight events.
  • Idle hooks hold no subscription. Every mounted useMutation used to hear every mutation-cache event forever just to filter it out; now cache events only fan out to hooks actually in flight.

Tests

Made with Cursor

The hook subscribed to the mutation cache at mount with a bare reactive
client() read — tripping Solid's STRICT_READ_UNTRACKED dev diagnostic
(reported by @brenelz in TanStack#11324) — and held that subscription for its
whole life even though the listener only matters between mutate and
settle. Rather than untracking the read, remove it: subscribe inside
run(), against the same client the mutation is built on, and unsubscribe
at the settle points (plus onCleanup for unmount mid-flight).
By construction: no reactive read at setup (nothing to untrack), the
listener and the mutation can never sit on different clients across a
QueryClient swap, and an idle useMutation holds no cache subscription —
mutation-cache events no longer fan out to every mounted hook.
Includes the TanStack#11324 regression test (no strict-read diagnostic on mount)
plus a listener-count test pinning the idle/flight/settled subscription
lifecycle.
Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b08366f7-a91d-4435-ad54-3037604deef8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@nx-cloud

nx-cloudBot commented Aug 29, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit afe2bf1

CommandStatusDurationResult
nx affected --targets=test:sherif,test:knip,tes...✅ Succeeded4m 25sView ↗
nx run-many --target=build --exclude=examples/*...✅ Succeeded17sView ↗

☁️ Nx Cloud last updated this comment at 2026-08-29 19:24:58 UTC

@pkg-pr-new

Copy link
Copy Markdown
More templates

@tanstack/angular-query-experimental

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

@tanstack/eslint-plugin-query

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

@tanstack/lit-query

npm i https://pkg.pr.new/@tanstack/lit-query@11325

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@11325

@tanstack/preact-query-devtools

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

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@11325

@tanstack/query-async-storage-persister

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

@tanstack/query-broadcast-client-experimental

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

@tanstack/query-core

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

@tanstack/query-devtools

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

@tanstack/query-persist-client-core

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

@tanstack/query-sync-storage-persister

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

@tanstack/react-query

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

@tanstack/react-query-devtools

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

@tanstack/react-query-next-experimental

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

@tanstack/react-query-persist-client

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

@tanstack/solid-query

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

@tanstack/solid-query-devtools

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

@tanstack/solid-query-persist-client

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

@tanstack/svelte-query

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

@tanstack/svelte-query-devtools

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

@tanstack/svelte-query-persist-client

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

@tanstack/vue-query

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

@tanstack/vue-query-devtools

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

commit: afe2bf1

@brenelz
brenelz merged commit 209f9f5 into TanStack:solid-query-v6-preAug 29, 2026
9 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 29, 2026
Sign up for freeto 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.

2 participants

@ryansolid@brenelz