From ed033564a99f5d677fd4bed7a308f71ce6342a25 Mon Sep 17 00:00:00 2001 From: Raashish Aggarwal <94279692+raashish1601@users.noreply.github.com> Date: Sat, 30 May 2026 19:06:42 +0530 Subject: [PATCH] feat(query-core): add retryAttempt to query error callback context Signed-off-by: Raashish Aggarwal <94279692+raashish1601@users.noreply.github.com> --- .../src/__tests__/queryCache.test.tsx | 26 ++++++++++++++++++- packages/query-core/src/query.ts | 3 +++ packages/query-core/src/queryCache.ts | 3 +++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/packages/query-core/src/__tests__/queryCache.test.tsx b/packages/query-core/src/__tests__/queryCache.test.tsx index 1238bcf44a9..4b8ef26f5ff 100644 --- a/packages/query-core/src/__tests__/queryCache.test.tsx +++ b/packages/query-core/src/__tests__/queryCache.test.tsx @@ -325,12 +325,36 @@ describe('queryCache', () => { }) await vi.advanceTimersByTimeAsync(100) const query = testCache.find({ queryKey: key }) - expect(onError).toHaveBeenCalledWith('error', query) + expect(onError).toHaveBeenCalledWith('error', query, { + retryAttempt: 0, + }) expect(onError).toHaveBeenCalledTimes(1) expect(onSuccess).not.toHaveBeenCalled() expect(onSettled).toHaveBeenCalledTimes(1) expect(onSettled).toHaveBeenCalledWith(undefined, 'error', query) }) + + it('should include retryAttempt in the onError context', async () => { + const key = queryKey() + const onError = vi.fn() + const testCache = new QueryCache({ onError }) + const testClient = new QueryClient({ queryCache: testCache }) + + testClient.prefetchQuery({ + queryKey: key, + queryFn: () => sleep(0).then(() => Promise.reject('error')), + retry: 2, + retryDelay: 0, + }) + + await vi.advanceTimersByTimeAsync(10) + + const query = testCache.find({ queryKey: key }) + expect(onError).toHaveBeenCalledTimes(1) + expect(onError).toHaveBeenCalledWith('error', query, { + retryAttempt: 2, + }) + }) }) describe('QueryCacheConfig success callbacks', () => { diff --git a/packages/query-core/src/query.ts b/packages/query-core/src/query.ts index 62bc9a16082..db0d7f8dd81 100644 --- a/packages/query-core/src/query.ts +++ b/packages/query-core/src/query.ts @@ -533,6 +533,7 @@ export class Query< } // Try to fetch the data + let latestFailureRetryCount = 0 this.#retryer = createRetryer({ initialPromise: fetchOptions?.initialPromise as | Promise @@ -548,6 +549,7 @@ export class Query< abortController.abort() }, onFail: (failureCount, error) => { + latestFailureRetryCount = failureCount this.#dispatch({ type: 'failed', failureCount, error }) }, onPause: () => { @@ -610,6 +612,7 @@ export class Query< this.#cache.config.onError?.( error as any, this as Query, + { retryAttempt: latestFailureRetryCount }, ) this.#cache.config.onSettled?.( this.state.data, diff --git a/packages/query-core/src/queryCache.ts b/packages/query-core/src/queryCache.ts index dd7123eaac8..fc585cfbd84 100644 --- a/packages/query-core/src/queryCache.ts +++ b/packages/query-core/src/queryCache.ts @@ -20,6 +20,9 @@ interface QueryCacheConfig { onError?: ( error: DefaultError, query: Query, + context: { + retryAttempt: number + }, ) => void onSuccess?: (data: unknown, query: Query) => void onSettled?: (