You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
solid-query: STRICT_READ_UNTRACKED on Solid 2 — client()/options() read in component body (useMutation, useBaseQuery) #11358
With Solid 2 (solid-js@2.0.0-rc.4) and @tanstack/solid-query@6.0.0-rc.1, every component that calls useMutation (and useQuery) logs a reactivity diagnostic on mount:
[STRICT_READ_UNTRACKED] Reactive value read directly in <UnitCard> will not update.
Move it into a tracking scope (JSX, a memo, or an effect's compute function).
[STRICT_READ_UNTRACKED] repair guide: node_modules/solid-js/skills/reactivity-diagnostics/SKILL.md
Solid 2 ships these diagnostics in dev builds, and they are meant to be actionable: the console is expected to stay clean. Right now a single screen with a handful of mutations produces dozens of them, which drowns out the diagnostics that are about application code.
Cause
The hooks read memos directly in the component body, outside any tracking scope.
packages/solid-query/src/useMutation.ts:
constclient=createMemo(()=>resolveClient())constobserver=newMutationObserver(client(),options())// ← read in component body
packages/solid-query/src/useBaseQuery.ts does the same when it creates its observer:
constinitialOptions=defaultedOptions()const[observer,setObserver]=createSignal(newObserver(client(),defaultedOptions()),// ← read in component body)
Both reads are intentional one-shot initialisations, so the value genuinely does not need to be tracked — which is exactly the case Solid's untrack exists for. Under Solid 1 this was silent; Solid 2 reports it.
Your minimal, reproducible example
Any component calling useMutation reproduces it. The official Solid 2 fullstack template does it out of the box:
src/routes/users.$id.tsx calls useMutation; open the page with a dev build of solid-js@2 and the diagnostic appears on every mount.
Steps to reproduce
Use solid-js@2.0.0-rc.4 with @tanstack/solid-query@6.0.0-rc.1.
Render any component that calls useMutation (or useQuery).
Watch the browser console on mount.
Expected behavior
No reactivity diagnostics from library code — the initial reads of client() / options() are untracked by design and should say so.
Suggested fix
Wrap the initialisation reads in untrack(...), or move observer creation into a createRenderEffect / memo. A related Solid-specific fix was already made in #10445 (useQueryClient running inside createMemo).
Platform
@tanstack/solid-query 6.0.0-rc.1 (latest rc on npm as of 2026-09-01)
solid-js 2.0.0-rc.4
Chromium 141, macOS
Note
Not filing a PR because I did not want to guess which of the two shapes (untrack vs. deferred observer creation) you prefer for v6 — happy to send one either way.
Hi! I'd like to work on this issue as my first open-source contribution. I can investigate the untrack approach and add the necessary regression tests. Please let me know if that's okay.
I'd like to take this one. STRICT_READ_UNTRACKED on Solid 2 means reads inside Solid's reactivity primitive are not auto-tracked — so client()/options() reads from a component body that should register as a query observer end up being one-shot reads, and the observer is never registered.
Root cause. In solid-query/src/QueryClient.ts (or solid-query/src/createBaseQuery.ts), the underlying createQuery calls client() and options() (which are functions returning the current client/options). On Solid 1 these returned Accessor<T> and the consumer component's tracking auto-wrapped. On Solid 2 with STRICT_READ_UNTRACKED, client()/options() must be read inside an explicit createMemo / effect to register — the current code calls them at module top level.
Alternatives I considered: (a) Wrap every client()/options() call site in an explicit createMemo (touches many files, IMO). (b) Add a createBaseQuery wrapper that runs client()/options() inside a createMemo once, memoizes, and exports the memoized version (cleanest). (c) Document: 'Solid 2 + STRICT_READ_UNTRACKED requires wrapping queries in createMemo' (workaround).
Suggestion to maintainer: (b) is the right fix — one wrapper, used by all queries. Two questions: (i) Does this regression also affect React Query / Vue Query (probably no, since they don't use Solid's tracking primitives) or is solid-query the only affected adapter? (ii) Is there an existing test that asserts the observer registration count > 0 after useQuery? (claiming via @LeonxLJX)
Activity
Anuj7953 commentedon Sep 4, 2026
Hi! I'd like to work on this issue as my first open-source contribution. I can investigate the
untrackapproach and add the necessary regression tests. Please let me know if that's okay.LeonxLJX commentedon Sep 4, 2026
I'd like to take this one.
STRICT_READ_UNTRACKEDon Solid 2 means reads inside Solid's reactivity primitive are not auto-tracked — soclient()/options()reads from a component body that should register as a query observer end up being one-shot reads, and the observer is never registered.Root cause. In
solid-query/src/QueryClient.ts(orsolid-query/src/createBaseQuery.ts), the underlyingcreateQuerycallsclient()andoptions()(which are functions returning the current client/options). On Solid 1 these returnedAccessor<T>and the consumer component's tracking auto-wrapped. On Solid 2 withSTRICT_READ_UNTRACKED,client()/options()must be read inside an explicitcreateMemo/effectto register — the current code calls them at module top level.Alternatives I considered: (a) Wrap every
client()/options()call site in an explicitcreateMemo(touches many files, IMO). (b) Add acreateBaseQuerywrapper that runsclient()/options()inside acreateMemoonce, memoizes, and exports the memoized version (cleanest). (c) Document: 'Solid 2 + STRICT_READ_UNTRACKED requires wrapping queries increateMemo' (workaround).Suggestion to maintainer: (b) is the right fix — one wrapper, used by all queries. Two questions: (i) Does this regression also affect React Query / Vue Query (probably no, since they don't use Solid's tracking primitives) or is solid-query the only affected adapter? (ii) Is there an existing test that asserts the observer registration count > 0 after
useQuery? (claiming via @LeonxLJX)fix(solid-query): untrack the one-shot client and options reads on mount