- [x ] I've validated the bug against the latest version of DB packages
Describe the bug
The initial error-propagation issue in #1260 (#1260) was recently resolved. While testing that fix with syncMode: 'on-demand', I found a further problem with that implementation.
After one filtered request succeeds, subsequent live queries that request different subsets do not enter the error state when their requests fail. This is a common use case for on-demand collections—for example, fetching different date ranges or ID ranges.
I would expect an error from a later filtered request to propagate to that specific live query, while existing live queries with usable data remain ready.
Tested with
- @tanstack/db: 0.8.3
- @tanstack/query-core: 5.102.2
- @tanstack/query-db-collection: 1.2.8
To Reproduce
import { QueryClient } from '@tanstack/query-core';
import { createCollection, createLiveQueryCollection, eq, parseLoadSubsetOptions } from '@tanstack/db';
import { queryCollectionOptions } from '@tanstack/query-db-collection';
const successfulTodoId = 'successful';
const failingTodoId = 'failing';
const requestedTodoIds = [];
let resolveSuccessfulTodoRequest;
const successfulTodoRequestFinished = new Promise((resolve) => {
resolveSuccessfulTodoRequest = resolve;
});
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});
const todoCollection = createCollection(
queryCollectionOptions({
queryKey: ['todos'],
queryClient,
retry: false,
syncMode: 'on-demand',
queryFn: async (context) => {
const requestedTodoId = parseLoadSubsetOptions(context.meta?.loadSubsetOptions).filters.find(
({ operator }) => operator === 'eq',
)?.value;
requestedTodoIds.push(String(requestedTodoId));
if (requestedTodoId === successfulTodoId) {
const result = [{ id: successfulTodoId, completed: false, text: 'Successful todo' }];
resolveSuccessfulTodoRequest();
return result;
}
if (requestedTodoId === failingTodoId) {
throw new Error('Failed to fetch filtered todos');
}
return [];
},
getKey: (todo) => todo.id,
}),
);
const successfulTodoQuery = createLiveQueryCollection({
query: (q) => q.from({ todo: todoCollection }).where(({ todo }) => eq(todo.id, successfulTodoId)),
startSync: true,
});
// Wait until the first live query and its backend request have completed.
await successfulTodoQuery.preload();
await successfulTodoRequestFinished;
if (JSON.stringify(requestedTodoIds) !== JSON.stringify([successfulTodoId])) {
throw new Error(`The successful query did not finish before the failing query started:
${JSON.stringify(requestedTodoIds)}`);
}
const failingTodoQuery = createLiveQueryCollection({
query: (q) => q.from({ todo: todoCollection }).where(({ todo }) => eq(todo.id, failingTodoId)),
startSync: true,
});
await failingTodoQuery.preload().catch(() => undefined);
console.log({
requestedTodoIds,
todoCollectionReady: todoCollection.isReady(),
todoCollectionHasError: todoCollection.utils.isError,
todoCollectionLastError: todoCollection.utils.lastError?.message,
successfulTodoQueryStatus: successfulTodoQuery.status,
failingTodoQueryStatus: failingTodoQuery.status,
});
Expected behavior
Expected output:
{
requestedTodoIds: ['successful', 'failing'],
todoCollectionReady: true,
todoCollectionHasError: true,
todoCollectionLastError: 'Failed to fetch filtered todos',
successfulTodoQueryStatus: 'ready',
failingTodoQueryStatus: 'error',
}
Actual output:
{
requestedTodoIds: ['successful', 'failing'],
todoCollectionReady: true,
todoCollectionHasError: true,
todoCollectionLastError: 'Failed to fetch filtered todos',
successfulTodoQueryStatus: 'ready',
failingTodoQueryStatus: 'ready',
}
Describe the bug
The initial error-propagation issue in #1260 (#1260) was recently resolved. While testing that fix with syncMode: 'on-demand', I found a further problem with that implementation.
After one filtered request succeeds, subsequent live queries that request different subsets do not enter the error state when their requests fail. This is a common use case for on-demand collections—for example, fetching different date ranges or ID ranges.
I would expect an error from a later filtered request to propagate to that specific live query, while existing live queries with usable data remain ready.
Tested with
To Reproduce
Expected behavior
Expected output:
Actual output: