Setup: Capacitor (or any WebView) SPA with @tanstack/query persistQueryClient over IndexedDB for offline reads.
Trap: TanStack Query's default networkMode: 'online' consults onlineManager before fetching. When the manager reports offline, a mounted query with NO persisted entry never attempts a fetch — it sits in isPending with fetchStatus: 'paused' indefinitely. UI built on isPending shows an infinite spinner instead of an error state. Queries WITH persisted data render fine (SWR), so the bug only appears on never-visited pages and is easy to miss in testing.
Compounding factor: in WebViews navigator.onLine (the default onlineManager signal) is unreliable, especially Android — it can report online while fetches fail, or offline while connected, making the pause behavior nondeterministic.
Fix that matches an offline-first read cache:
networkMode: 'offlineFirst'in QueryClient defaults — first attempt always fires (fails fast offline →isError→ your no-cached-fallback error UI), retries pause and auto-resume on reconnect; cached queries keep serving stale data.- Wire onlineManager to a reliable native signal:
onlineManager.setEventListener((setOnline) => connectivityStore.subscribe(setOnline))where the store is fed by @capacitor/network'snetworkStatusChangeon native and falls back to navigator.onLine on web. This also makesrefetchOnReconnectactually fire when connectivity returns.
Both changes are two lines each once you have a connectivity store; neither requires touching individual queries.