persistQueryClientSubscribe drops the persistQueryClientSave promise, causing unhandled rejections when persisting fails
persistQueryClientSubscribe calls persistQueryClientSave(props) on every cache event, but it doesn't handle the returned promise. So if saving fails, I get an unhandled promise rejection on each cache update.
I noticed this while reading the code and confirmed it with a test. It can happen with a custom persister like the IndexedDB example in the docs, because set() from idb-keyval can reject, for example with QuotaExceededError or DataCloneError. It can also happen with the built-in persisters if a dehydrateOptions callback like shouldDehydrateQuery throws.
Small repro:
const queryClient = new QueryClient()
persistQueryClientSubscribe({
queryClient,
persister: {
persistClient: () => Promise.reject(new Error('quota exceeded')),
restoreClient: () => undefined,
removeClient: () => undefined,
},
})
queryClient.setQueryData(['a'], 1) // -> unhandled rejectionThis affects all the persist providers, since they all use persistQueryClientSubscribe. That includes Vue's clientPersister when it's used with persistQueryClient().
The restore side already catches errors and logs a warning in dev (#8969), but the save side doesn't. I know error handling has mostly been left to the persister (#3527), so I'm not sure which way you'd prefer:
- catch it in
persistQueryClientSubscribeand log in dev, same as restore - keep the code as is, and add a
try/catchto the IndexedDB example in the docs
I'm happy to send a PR for either one.
Source: TanStack/query