Files
gh-jezweb-claude-skills-ski…/references/top-errors.md
2025-11-30 08:25:35 +08:00

6.6 KiB

Top TanStack Query Errors & Solutions

Complete error reference with fixes


Error #1: Object Syntax Required

Error Message:

TypeError: useQuery is not a function
Property 'queryKey' does not exist on type...

Why: v5 removed function overloads, only object syntax works

Fix:

// ❌ v4 syntax
useQuery(['todos'], fetchTodos)

// ✅ v5 syntax
useQuery({ queryKey: ['todos'], queryFn: fetchTodos })

Source: v5 Migration Guide


Error #2: Query Callbacks Not Working

Error Message:

Property 'onSuccess' does not exist on type 'UseQueryOptions'

Why: onSuccess, onError, onSettled removed from queries (still work in mutations)

Fix:

// ❌ v4
useQuery({
  queryKey: ['todos'],
  queryFn: fetchTodos,
  onSuccess: (data) => console.log(data)
})

// ✅ v5 - Use useEffect
const { data } = useQuery({ queryKey: ['todos'], queryFn: fetchTodos })
useEffect(() => {
  if (data) console.log(data)
}, [data])

Source: v5 Breaking Changes


Error #3: isLoading Always False

Error Message: No error, but isLoading is false during initial fetch

Why: v5 changed isLoading meaning: now isPending && isFetching

Fix:

// ❌ v4
const { isLoading } = useQuery(...)
if (isLoading) return <Loading />

// ✅ v5
const { isPending } = useQuery(...)
if (isPending) return <Loading />

Source: v5 Migration


Error #4: cacheTime Not Recognized

Error Message:

Property 'cacheTime' does not exist on type 'UseQueryOptions'

Why: Renamed to gcTime (garbage collection time)

Fix:

// ❌ v4
cacheTime: 1000 * 60 * 60

// ✅ v5
gcTime: 1000 * 60 * 60

Source: v5 Migration


Error #5: useSuspenseQuery + enabled

Error Message:

Property 'enabled' does not exist on type 'UseSuspenseQueryOptions'

Why: Suspense guarantees data is available, can't conditionally disable

Fix:

// ❌ Wrong
useSuspenseQuery({
  queryKey: ['todo', id],
  queryFn: () => fetchTodo(id),
  enabled: !!id,
})

// ✅ Correct: Conditional rendering
{id ? <TodoComponent id={id} /> : <div>No ID</div>}

Source: GitHub Discussion #6206


Error #6: initialPageParam Required

Error Message:

Property 'initialPageParam' is missing in type 'UseInfiniteQueryOptions'

Why: v5 requires explicit initialPageParam for infinite queries

Fix:

// ❌ v4
useInfiniteQuery({
  queryKey: ['projects'],
  queryFn: ({ pageParam = 0 }) => fetchProjects(pageParam),
  getNextPageParam: (lastPage) => lastPage.nextCursor,
})

// ✅ v5
useInfiniteQuery({
  queryKey: ['projects'],
  queryFn: ({ pageParam }) => fetchProjects(pageParam),
  initialPageParam: 0, // Required
  getNextPageParam: (lastPage) => lastPage.nextCursor,
})

Source: v5 Migration


Error #7: keepPreviousData Not Working

Error Message:

Property 'keepPreviousData' does not exist on type 'UseQueryOptions'

Why: Replaced with placeholderData function

Fix:

// ❌ v4
keepPreviousData: true

// ✅ v5
import { keepPreviousData } from '@tanstack/react-query'

placeholderData: keepPreviousData

Source: v5 Migration


Error #8: TypeScript Error Type

Error Message: Type errors when handling non-Error objects

Why: v5 defaults to Error type instead of unknown

Fix:

// If throwing non-Error types, specify explicitly:
const { error } = useQuery<DataType, string>({
  queryKey: ['data'],
  queryFn: async () => {
    if (fail) throw 'custom error string'
    return data
  },
})

// Better: Always throw Error objects
throw new Error('Custom error')

Source: v5 Migration


Error #9: Query Not Refetching

Symptoms: Data never updates even when stale

Why: Usually config issue - check staleTime, refetch options

Fix:

// Check these settings
useQuery({
  queryKey: ['todos'],
  queryFn: fetchTodos,
  staleTime: 0, // Data stale immediately
  refetchOnWindowFocus: true,
  refetchOnMount: true,
  refetchOnReconnect: true,
})

// Or manually refetch
const { refetch } = useQuery(...)
refetch()

// Or invalidate
queryClient.invalidateQueries({ queryKey: ['todos'] })

Error #10: Mutations Not Invalidating

Symptoms: UI doesn't update after mutation

Why: Forgot to invalidate queries

Fix:

useMutation({
  mutationFn: addTodo,
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['todos'] }) // ✅ Required
  },
})

Error #11: Network Errors Not Caught

Symptoms: App crashes on network errors

Why: Not handling errors properly

Fix:

// Always handle errors
const { data, error, isError } = useQuery({
  queryKey: ['todos'],
  queryFn: async () => {
    const response = await fetch('/api/todos')
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`) // ✅ Throw errors
    }
    return response.json()
  },
})

if (isError) return <div>Error: {error.message}</div>

Error #12: Stale Closure in Callbacks

Symptoms: Mutation callbacks use old data

Why: Closure captures stale values

Fix:

// ❌ Stale closure
const [value, setValue] = useState(0)
useMutation({
  onSuccess: () => {
    console.log(value) // Stale!
  },
})

// ✅ Use functional update
useMutation({
  onSuccess: () => {
    setValue(prev => prev + 1) // Fresh value
  },
})

Quick Diagnosis Checklist

  • Using v5 object syntax?
  • Using isPending instead of isLoading?
  • Using gcTime instead of cacheTime?
  • No query callbacks (onSuccess, etc.)?
  • initialPageParam present for infinite queries?
  • Throwing errors in queryFn?
  • Invalidating queries after mutations?
  • Check DevTools for query state