TanStack / TanStack/query

[query-broadcast-client-experimental] Since 5.102.0 a newly mounted query overwrites the same query's resolved data in every other tab

Open
#11,391 0 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
50.3k
Forks
4.2k
Avg merge
18h 25m
Merged PRs (30d)
200

Description

Describe the bug

Since 5.102.0 the added message carries the new query's initial state (status: 'pending', data: undefined). In every other tab the receiver does query.setState(state) when that query already exists, so a tab that has already fetched the query loses its data and goes back to pending.

In 5.101.4 the added message carried no state, and setState(undefined) was a no-op.

The change came in with #10771 (safePost refactor), where state was added to the added message along with the typed message union.

Your minimal, reproducible example

Two QueryClients in one process, wired with broadcastQueryClient over broadcast-channel's in-memory simulate transport:

import { broadcastQueryClient } from '@tanstack/query-broadcast-client-experimental'
import { QueryClient } from '@tanstack/query-core'

const wait = () => new Promise((r) => setTimeout(r, 50))
const key = ['k']

const tabA = new QueryClient()
const tabB = new QueryClient()
broadcastQueryClient({ queryClient: tabA, broadcastChannel: 'x', options: { type: 'simulate' } })
broadcastQueryClient({ queryClient: tabB, broadcastChannel: 'x', options: { type: 'simulate' } })

tabA.setQueryData(key, { data: 'value' })
tabB.getQueryCache().build(tabB, { queryKey: key }) // what a hook mounting in a new tab does

await wait()
console.log(tabA.getQueryState(key)?.status, tabA.getQueryData(key))
// 5.101.4: success { data: 'value' }
// 5.102.0+: pending undefined

Steps to reproduce

  1. Open the app in tab 1 and let a query resolve.
  2. Open tab 2, which mounts the same query.
  3. Tab 1's query is now pending with no data.

Expected behavior

A tab that has already resolved a query keeps it when another tab mounts the same query. The new tab should receive the existing data (via the updated message), not the other way round.

How often does this bug happen?

Every time

Platform

  • Package: @tanstack/query-broadcast-client-experimental 5.102.0 through 5.102.8 (5.101.4 is fine)
  • Browser: any; also reproduces in Node with the simulate transport

Additional context

In our app this wiped the auth-config query in every open tab, which cascaded into requests without a token and a forced sign-out of all tabs. Suggested fix: on added, do not call setState on a query that already exists in the receiving cache (or only when the local query has no data); only build it when missing.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at broadcastQueryClient's handling of the added message and reproduce the issue with two QueryClients using broadcast-channel's in-memory simulate transport. Verify that mounting an existing query does not replace resolved data with the pending initial state, while a new tab still receives the existing data through the updated message.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
distributed-systems
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.