[query-broadcast-client-experimental] broadcastQueryClient: an `added` event overwrites a receiving query that has no data (e.g. in error) with the sender's empty state
Maintainer thường phản hồi trong vòng 1 ngày
@lazerg đang làm issue này rồi.
Từ ngày 20/10/2026.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 25/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- react, typescript
- Lĩnh vực
- backend-api-design, frontend
Hướng nghiên cứu
Read src/index.ts around lines 155–162 and 193–198 in the broadcast client package, then inspect the related change in #11391. The open pull request #12215 is already linked to this issue. Done means an added event no longer replaces a receiver’s settled error state with an empty pending state; the issue includes a minimal reproduction to check that behavior.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Package: @tanstack/query-broadcast-client-experimental 5.104.3 (with @tanstack/query-core 5.104.3)
Describe the bug
When another tab creates a query, the receiving tab applies the sender's state on added whenever its own query has no data. A query that has no data but did settle (a failed query: status: 'error', errorUpdatedAt > 0) is replaced with the sender's brand-new state: status: 'pending', fetchStatus: 'idle', error: null, dataUpdatedAt: 0, errorUpdatedAt: 0.
The receiving query now looks like it is loading, but no fetch runs. Observers render a pending/loading UI indefinitely (until a refetch interval, focus or invalidation happens to trigger), and the error is lost.
src/index.ts, lines 193-198:
} else if (type === 'added') {
if (query) {
if (query.state.data === undefined) {
query.setState(state)
}
return
}
The sender posts added straight from queryCache.build, before its fetch starts (lines 155-162), so the state it carries is the initial empty state:
if (queryEvent.type === 'added') {
safePost({
type: 'added',
queryHash,
queryKey,
state,
})
}
Minimal reproduction
- Tab A and tab B both call
broadcastQueryClient({ queryClient }). - In tab A,
useQuery({ queryKey: ['x'], queryFn: () => Promise.reject(new Error('down')), retry: false }). It settles instatus: 'error', with no data. - Tab B creates the same query: either mount the same
useQuery, orqueryClient.getQueryCache().build(queryClient, { queryKey: ['x'] })(for example, as a side effect of a prefetch that has not started yet). - In tab A, the query is now
status: 'pending',fetchStatus: 'idle',error: null,errorUpdatedAt: 0. The observer shows loading, and no request is in flight.
Without the plugin, the same can be shown in a single client:
const query = queryClient.getQueryCache().find({ queryKey: ['x'] })! // in error, no data
query.setState({ status: 'pending', fetchStatus: 'idle', data: undefined, dataUpdatedAt: 0, error: null, errorUpdatedAt: 0 })
// observers now report pending with no fetch running
Expected behavior
An added event carries nothing the receiver lacks when the sender's query has never settled. The receiver should keep its own state, in particular an error.
Suggested fix
Skip an incoming added state that never received data or an error:
} else if (type === 'added') {
if (query) {
const incoming = state as QueryState
if (
query.state.data === undefined &&
(incoming.dataUpdatedAt > 0 || incoming.errorUpdatedAt > 0)
) {
query.setState(incoming)
}
return
}
A stricter variant would apply added only when it is newer than the receiver's last outcome (max(dataUpdatedAt, errorUpdatedAt)).
Workaround we use
Our query projection detects an observed query left pending with fetchStatus: 'idle' and refetches it once through its observer.
Related
Follow-up to #11391, which made added skip a receiver that already has data. A receiver without data but with an error is still overwritten.
- Ngôn ngữ chính
- TypeScript
- Star
- 50.4k
- Fork
- 4.3k
- Merge trung bình
- 9 giờ 42 phút
- Pull request đã merge (30 ngày)
- 590
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của TanStack/query
-
QueryClient.isFetching and useIsFetching accept a fetchStatus filter and ignore itCó thể đã có người làm @Apu-Emdad đã nhận 8 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
solid-query: STRICT_READ_UNTRACKED on Solid 2 — client()/options() read in component body (useMutation, useBaseQuery)Có thể làm lại được @LeonxLJX đã nhận 48 ngày trước và không có pull request nào đang mở. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
TanStack/query#11358 · 2 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
useBaseQuery fetches the old query key when an <Activity> tree is revealedCó thể đã có người làm @lazerg đã nhận 1 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 35/100
Maintainer thường phản hồi trong vòng 1 ngày
-
solid-query 6.0.0-rc.5: onCacheEvent throws NotReadyError during a Solid 2 (rc.14+) transition landingCó thể đã có người làm @UzumakiODZ đã nhận 7 ngày trước. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 28/100
TanStack/query#12031 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Explicit gcTime schedules a GC timer during SSR, retaining the whole render in memoryCó thể đã có người làm @AdzerKI đã nhận 8 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 25/100
TanStack/query#12025 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của TanStack/query
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
kunchenguid/gh-axi#220 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 79/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Maintainer thường phản hồi trong vòng 1 ngày
-
prerender: wait for env-runner worker readiness before crawlingCó thể đã có người làm @sarankumar1325 đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 1 ngày