TanStack/query · critical

${this.queryHash} data is undefined

Error message

${this.queryHash} data is undefined

What it means

Runtime guard in `Query` (`@tanstack/query-core`) after `this.#retryer.start()` resolves. The query function MUST return a defined value; `undefined` is treated as 'no data' because it would make cache state ambiguous and break `data`/`status` semantics. The console error prints the affected `queryHash`, then the same message is thrown to fail the observer.

Source

Thrown at packages/query-core/src/query.ts:575

        this.#dispatch({ type: 'continue' })
      },
      retry: context.options.retry,
      retryDelay: context.options.retryDelay,
      networkMode: context.options.networkMode,
      canRun: () => true,
    })

    try {
      const data = await this.#retryer.start()
      // this is more of a runtime guard
      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
      if (data === undefined) {
        if (process.env.NODE_ENV !== 'production') {
          console.error(
            `Query data cannot be undefined. Please make sure to return a value other than undefined from your query function. Affected query key: ${this.queryHash}`,
          )
        }
        throw new Error(`${this.queryHash} data is undefined`)
      }

      this.setData(data)

      // Notify cache callback
      this.#cache.config.onSuccess?.(data, this as Query<any, any, any, any>)
      this.#cache.config.onSettled?.(
        data,
        this.state.error as any,
        this as Query<any, any, any, any>,
      )
      return data
    } catch (error) {
      if (error instanceof CancelledError) {
        if (error.silent) {
          // silent cancellation implies a new fetch is going to be started,
          // so we piggyback onto that promise
          return this.#retryer.promise

View on GitHub (pinned to 159982c80b)

Solutions

  1. Inspect the queryFn for the matching `queryHash` and ensure every code path returns a non-undefined value.
  2. Add `return data;` explicitly and avoid bare `return;`.
  3. If absence is legitimate, model it as `null` and type `TData` accordingly, or split into a separate query that is conditionally enabled.
  4. Add a test asserting the queryFn returns a defined value for the representative inputs.

Example fix

// before
queryFn: async () => {
  const res = await fetch('/api/user')
  const json = await res.json()
  // forgot to return
}
// after
queryFn: async () => {
  const res = await fetch('/api/user')
  return res.json()
}
Defensive patterns

Strategy: validation

Validate before calling

// Wrap your queryFn to assert a non-undefined return at runtime.
function withDefinedReturn<T>(fn: () => Promise<T>): () => Promise<NonNullable<T>> {
  return async () => {
    const data = await fn()
    if (data === undefined) throw new Error('queryFn returned undefined')
    return data as NonNullable<T>
  }
}

Try / catch

// In an observer error handler, surface the affected queryHash.
catch (e) {
  if (e instanceof Error && /data is undefined/.test(e.message)) {
    reportIssue(e.message) // contains the queryHash
  }
  throw e
}

Prevention

When it happens

Trigger: A `queryFn` with an early `return;` or `return undefined`; a `queryFn` whose only `return` is inside a conditional branch that isn't taken; a `queryFn` that calls an API and forgets to return the response (`api.get()` without `return`); arrow-function shorthand that implicitly returns the wrong expression.

Common situations: Async functions where a code path falls through without returning; refactoring a queryFn and dropping the `return` keyword; `select` returning `undefined`; conditional fetch that returns nothing on a branch; integration tests with mock queryFns returning `undefined`.

Related errors


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