marmelab/react-admin · error · Error
Found getManyReference result in cache without total or page
Error message
Found getManyReference result in cache without total or pageInfo
What it means
After a delete, useDeleteMany updates the cached getManyReference result (the list of related records). The optimistic cache update needs to know the collection size, which it derives from either total (offset pagination) or pageInfo (cursor pagination). If neither field exists in the cached result, react-admin refuses to update it and throws.
Source
Thrown at packages/ra-core/src/dataProvider/useDeleteMany.ts:244
if (!recordWasFound) {
return res;
}
if (res.total) {
return {
...res,
data: newCollection,
total:
res.total -
(res.data.length - newCollection.length),
};
}
if (res.pageInfo) {
return {
...res,
data: newCollection,
};
}
throw new Error(
'Found getManyReference result in cache without total or pageInfo'
);
},
{ updatedAt }
);
return params.ids;
},
getQueryKeys: ({ resource }) => {
const queryKeys = [
[resource, 'getList'],
[resource, 'getInfiniteList'],
[resource, 'getMany'],
[resource, 'getManyReference'],
];
return queryKeys;
},
onSettled: (...args) => {View on GitHub (pinned to 051f511bb0)
Solutions
- Make the data provider's getManyReference return { data, total } (or { data, pageInfo } for cursor pagination).
- Ensure the list query that populates the cache is fetched through useGetManyReference so the cache shape matches.
- If using a mock provider in tests, include total: data.length in getManyReference responses.
Example fix
// before
getManyReference: (resource, params) =>
Promise.resolve({ data: filtered });
// after
getManyReference: (resource, params) =>
Promise.resolve({ data: filtered, total: filtered.length }); Defensive patterns
Strategy: validation
Validate before calling
const res = await dataProvider.getManyReference(resource, params);
if (res.total == null && res.pageInfo == null) {
throw new Error('getManyReference must return total or pageInfo');
} Type guard
const hasListMeta = (r: { total?: number; pageInfo?: unknown }): r is { total: number } | { pageInfo: object } =>
r.total != null || r.pageInfo != null; Try / catch
try {
await mutate(resource, { ids });
} catch (e) {
if (e instanceof Error && e.message.includes('total or pageInfo')) {
invalidateCache(); // refetch list without optimistic update
} else throw e;
} Prevention
- Always include total (or pageInfo) in getManyReference responses.
- Test custom data providers against react-admin's provider contract.
- Keep mocks in tests shape-compatible with real responses.
When it happens
Trigger: A custom data provider returns getManyReference data without total and without pageInfo; the cache was populated by a non-standard query that shaped the result differently; calling useDeleteMany inside a ReferenceManyField-like list whose provider omits pagination metadata.
Common situations: Custom or third-party data providers that return only { data } from getManyReference; migrating a provider built for an older react-admin contract; mocking providers in tests that forget total/pageInfo.
Related errors
- Invalid dataProvider response for create: missing id
- ra.notification.data_provider_error
- Missing dataProvider prop. React-admin requires a valid data
- ra.navigation.page_out_of_boundaries
- When not redirecting after editing, query meta and mutation
AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30).
Data as JSON: /api/errors/e1be5a06f4b4eb2d.
Report an issue: GitHub.