TanStack/query · error

Bad argument type. Starting with v5, only the "Object" form

Error message

Bad argument type. Starting with v5, only the "Object" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object

What it means

Dev-only runtime guard in React Query's `useBaseQuery` (mirror of the Preact equivalent). v5 removed the positional-argument overloads in favor of a single options object; if the first argument is not a plain object (or is an array), the hook rejects it before creating an observer. Only fires outside production builds.

Source

Thrown at packages/react-query/src/useBaseQuery.ts:46

  TQueryFnData,
  TError,
  TData,
  TQueryData,
  TQueryKey extends QueryKey,
>(
  options: UseBaseQueryOptions<
    TQueryFnData,
    TError,
    TData,
    TQueryData,
    TQueryKey
  >,
  Observer: typeof QueryObserver,
  queryClient?: QueryClient,
): QueryObserverResult<TData, TError> {
  if (process.env.NODE_ENV !== 'production') {
    if (typeof options !== 'object' || Array.isArray(options)) {
      throw new Error(
        'Bad argument type. Starting with v5, only the "Object" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object',
      )
    }
  }

  const isRestoring = useIsRestoring()
  const errorResetBoundary = useQueryErrorResetBoundary()
  const client = useQueryClient(queryClient)
  const defaultedOptions = client.defaultQueryOptions(options)
  ;(client.getDefaultOptions().queries as any)?._experimental_beforeQuery?.(
    defaultedOptions,
  )

  const query = client
    .getQueryCache()
    .get<
      TQueryFnData,
      TError,

View on GitHub (pinned to 159982c80b)

Solutions

  1. Migrate to the object form: `useQuery({ queryKey, queryFn })`.
  2. Run `npx @tanstack/query-codemods remove-overloads` on the project.
  3. Audit all `useQuery`/`useInfiniteQuery`/`useMutation` calls to confirm they pass a single object.
  4. Refactor wrapper hooks to accept and forward an options object.

Example fix

// before
useQuery(['todos'], fetchTodos, { enabled: false })
// after
useQuery({ queryKey: ['todos'], queryFn: fetchTodos, enabled: false })
Defensive patterns

Strategy: type-guard

Validate before calling

function assertQueryOptionsObject(options: unknown) {
  if (options === null || typeof options !== 'object' || Array.isArray(options)) {
    throw new TypeError('useQuery expects a single options object in v5')
  }
}

Type guard

const isPlainOptionsObject = (v: unknown): v is Record<string, unknown> =>
  v !== null && typeof v === 'object' && !Array.isArray(v)

Try / catch

// Temporary compatibility shim during migration.
function safeUseQuery(arg: any, fn?: any, rest?: any) {
  if (Array.isArray(arg) || typeof arg === 'string') return useQuery({ queryKey: Array.isArray(arg) ? arg : [arg], queryFn: fn, ...(rest || {}) })
  return useQuery(arg)
}

Prevention

When it happens

Trigger: Calling `useQuery(['key'], fn)` or `useQuery('key', fn)` (v4 form) under v5; passing a query-key array as the first argument; passing `null`/`undefined`; partial v4->v5 migration leaving some call sites on the old signature.

Common situations: Upgrading `@tanstack/react-query` from v4 to v5 without running the codemod; copying v4 examples; a custom hook that forwards positional args; libraries that wrap `useQuery` and still use the old signature.

Related errors


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