Skip to content

Documentation mismatch: invalidateQueries default behavior claims "all" but only refetches "active" queries #9531

@armspkt

Description

@armspkt

Describe the bug

The documentation for queryClient.invalidateQueries() states that the type parameter defaults to 'all', which should invalidate and refetch all matching queries (both active and inactive). However, the actual behavior only refetches active queries by default, leaving inactive cached queries stale.

Your minimal, reproducible example

https://codesandbox.io/p/sandbox/wpgfzw

Steps to reproduce

  1. Create queries with the same prefix (e.g., ['todos'], ['todos', 1], ['todos', 2])
  2. Prefetch an additional query to create an inactive cached query (e.g., ['todos', 3])
  3. Call queryClient.invalidateQueries({ queryKey: ['todos'] })
  4. Observe that only active queries refetch, while inactive cached queries remain stale

Expected behavior

According to the documentation, queryClient.invalidateQueries({ queryKey: ['todos'] }) should:

  • Invalidate ALL queries with keys starting with ['todos']
  • Refetch ALL matching queries (both active and inactive)

Actual behavior

queryClient.invalidateQueries({ queryKey: ['todos'] }) only:

  • Refetches queries that have active observers (components using them)
  • Leaves inactive cached queries (like prefetched queries) stale

How often does this bug happen?

None

Screenshots or Videos

No response

Platform

  • OS: macOS/Windows/Linux
  • Browser: Chrome/Firefox/Safari (any)
  • Version of TanStack Query: 5.84.1
  • React version: 18.0.0+

Tanstack Query adapter

None

TanStack Query version

5.84.1

TypeScript version

No response

Additional context

Root cause analysis:
The issue appears to be in the invalidation logic where the default refetch behavior uses 'active' instead of 'all' despite documentation claiming otherwise.

Workaround:
Explicitly specify type: 'all' to get the documented behavior:

queryClient.invalidateQueries({ queryKey: ['todos'], type: 'all' })

Impact:
This discrepancy can cause subtle bugs where developers expect all cached data to be refreshed after mutations, but inactive cached queries remain stale, potentially leading to inconsistent application state.

Documentation references:

  • The documentation states that type defaults to 'all'
  • However, the actual implementation appears to default to 'active' behavior

Steps to Reproduce (Detailed)

### Detailed Reproduction Steps

1. **Setup queries with staleTime: Infinity**
   ```javascript
   const queryClient = new QueryClient({
     defaultOptions: {
       queries: { staleTime: Infinity }
     }
   });
  1. Create multiple queries with same prefix

    // Active queries
    useQuery({ queryKey: ['todos'], queryFn: fetchTodos });
    useQuery({ queryKey: ['todos', 1], queryFn: () => fetchTodosPage(1) });
    
    // Inactive cached query (prefetched)
    queryClient.prefetchQuery({
      queryKey: ['todos', 3],
      queryFn: () => fetchTodosPage(3)
    });
  2. Test invalidation behavior

    // This should refetch ALL queries according to docs
    queryClient.invalidateQueries({ queryKey: ['todos'] });
  3. Observe the results

    • ✅ Active queries: Get new fetch timestamps
    • ❌ Inactive cached queries: Keep old fetch timestamps
  4. Test workaround

    // This works as expected
    queryClient.invalidateQueries({ queryKey: ['todos'], type: 'all' });
  5. Verify fix

    • ✅ Active queries: Get new fetch timestamps
    • ✅ Inactive cached queries: Also get new fetch timestamps

Suggested Fix

Suggested Solution

Option 1: Fix Documentation
Update documentation to clarify that the default behavior only refetches active queries, and type: 'all' is required for all queries.

Option 2: Fix Implementation
Change the default behavior to match documentation by making type: 'all' the actual default.

Option 3: Breaking Change Warning
If changing the default behavior, consider it a breaking change and document the migration path.

Preference: Option 1 (documentation fix) would be safest for existing applications, but Option 2 (implementation fix) would match user expectations better.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions