TanStack/query · error

No QueryClient found

Error message

No QueryClient found

What it means

Thrown by `getResolvedQueryClient()` inside the `withDevtools` environment initializer effect when `devtoolsOptions().client ?? injectedClient` is falsy. `withDevtools` is meant to be added to `provideTanStackQuery` alongside the QueryClient provider; if the client token is absent from DI and the devtools options callback did not supply one, devtools cannot attach to anything and abort.

Source

Thrown at packages/angular-query-experimental/src/devtools/with-devtools.ts:109

          })
          const destroyRef = inject(DestroyRef)
          const devtoolsOptions = inject(DEVTOOLS_OPTIONS_SIGNAL)
          const injector = inject(Injector)

          let devtools: TanstackQueryDevtools | null = null
          let el: HTMLElement | null = null

          const shouldLoadToolsSignal = computed(() => {
            const { loadDevtools } = devtoolsOptions()
            return typeof loadDevtools === 'boolean'
              ? loadDevtools
              : isDevMode()
          })

          const getResolvedQueryClient = () => {
            const client = devtoolsOptions().client ?? injectedClient
            if (!client) {
              throw new Error('No QueryClient found')
            }
            return client
          }

          const destroyDevtools = () => {
            devtools?.unmount()
            el?.remove()
            devtools = null
          }

          effect(
            () => {
              const shouldLoadTools = shouldLoadToolsSignal()
              const {
                client,
                position,
                errorTypes,
                buttonPosition,

View on GitHub (pinned to 159982c80b)

Solutions

  1. Pass a `QueryClient` to `provideTanStackQuery`: `provideTanStackQuery(new QueryClient(), withDevtools())`.
  2. If you supply the client dynamically, return it from the devtools options function: `withDevtools(() => ({ client: clientSignal() }))`.
  3. Confirm the `QueryClient` is in the root injector and not gated behind a lazy-loaded route that initializes after the environment initializer runs.
  4. Temporarily remove `withDevtools` to verify the QueryClient provider is wired, then re-add it.

Example fix

// before
providers: [provideTanStackQuery(), withDevtools()]
// after
providers: [provideTanStackQuery(new QueryClient(), withDevtools())]
Defensive patterns

Strategy: validation

Validate before calling

// Verify both sources before relying on getResolvedQueryClient.
const ensureDevtoolsClient = (optsClient: unknown, injected: QueryClient | null): QueryClient => {
  const c = (optsClient as QueryClient) ?? injected
  if (!c) throw new Error('withDevtools: no QueryClient in DI or options.client')
  return c
}

Type guard

const hasClient = (o: { client?: unknown }): o is { client: QueryClient } =>
  !!o.client && typeof o.client.getQueryCache === 'function'

Try / catch

// In the effect, degrade gracefully if the client is missing.
try { const client = getResolvedQueryClient() /* ... */ }
catch (e) { console.warn('[withDevtools]', (e as Error).message) }

Prevention

When it happens

Trigger: Using `withDevtools()` in `provideTanStackQuery` while NOT passing a `QueryClient` as the first argument to `provideTanStackQuery`; calling `withDevtools` via `queryFeature` outside of `provideTanStackQuery`; providing the `QueryClient` in a sibling/lazy injector that the devtools environment initializer cannot see.

Common situations: Calling `provideTanStackQuery()` with no `QueryClient` argument; splitting providers so `withDevtools` lands in a different injector from the client; upgrading from an older Angular Query setup that registered the client under a different token; providing `withDevtools` twice or in a child injector that lacks the client.

Related errors


AI-assisted analysis of TanStack/query@159982c80b (2026-08-12). Data as JSON: /api/errors/13dd6de7808da9af. Report an issue: GitHub.