diff --git a/.changeset/fuzzy-rats-mutate.md b/.changeset/fuzzy-rats-mutate.md
new file mode 100644
index 00000000000..fafbc165772
--- /dev/null
+++ b/.changeset/fuzzy-rats-mutate.md
@@ -0,0 +1,5 @@
+---
+'@tanstack/react-query': patch
+---
+
+Allow queries with falsy errors to retry on mount when `throwOnError` returns false.
diff --git a/packages/react-query/src/__tests__/useQuery.test.tsx b/packages/react-query/src/__tests__/useQuery.test.tsx
index 520e80fc673..ab15a3aa454 100644
--- a/packages/react-query/src/__tests__/useQuery.test.tsx
+++ b/packages/react-query/src/__tests__/useQuery.test.tsx
@@ -6802,6 +6802,35 @@ describe('useQuery', () => {
expect(queryFn).toHaveBeenCalledTimes(2)
})
+ it('should retry on mount when throwOnError returns false for a falsy error', async () => {
+ const key = queryKey()
+ const queryFn = vi.fn(() => Promise.reject())
+
+ function Component() {
+ const { status } = useQuery({
+ queryKey: key,
+ queryFn,
+ throwOnError: () => false,
+ retryOnMount: () => true,
+ staleTime: Infinity,
+ retry: false,
+ })
+
+ return
{status}
+ }
+
+ const rendered1 = renderWithClient(queryClient, )
+ await vi.advanceTimersByTimeAsync(0)
+ expect(rendered1.getByTestId('status')).toHaveTextContent('error')
+ expect(queryFn).toHaveBeenCalledTimes(1)
+ rendered1.unmount()
+
+ const rendered2 = renderWithClient(queryClient, )
+ await vi.advanceTimersByTimeAsync(0)
+ expect(rendered2.getByTestId('status')).toHaveTextContent('error')
+ expect(queryFn).toHaveBeenCalledTimes(2)
+ })
+
it('should not retry on mount when throwOnError function returns true', async () => {
const key = queryKey()
let fetchCount = 0
diff --git a/packages/react-query/src/errorBoundaryUtils.ts b/packages/react-query/src/errorBoundaryUtils.ts
index a27036f9a2c..f1170c17c8e 100644
--- a/packages/react-query/src/errorBoundaryUtils.ts
+++ b/packages/react-query/src/errorBoundaryUtils.ts
@@ -27,10 +27,14 @@ export const ensurePreventErrorBoundaryRetry = <
errorResetBoundary: QueryErrorResetBoundaryValue,
query: Query | undefined,
) => {
- const throwOnError =
- query?.state.error && typeof options.throwOnError === 'function'
- ? shouldThrowError(options.throwOnError, [query.state.error, query])
- : options.throwOnError
+ let throwOnError = options.throwOnError
+
+ if (query?.state.status === 'error' && typeof throwOnError === 'function') {
+ throwOnError = shouldThrowError(throwOnError, [
+ query.state.error as TError,
+ query,
+ ])
+ }
if (options.suspense || throwOnError) {
// Prevent retrying failed query if the error boundary has not been reset yet