marmelab/react-admin · error · Error
useUpdateMany mutation requires an array of ids
Error message
useUpdateMany mutation requires an array of ids
What it means
react-admin's useUpdateMany hook validates its mutate arguments before calling the dataProvider. If params.ids is null or undefined it throws immediately, because updateMany is meaningless without the list of record ids to update.
Source
Thrown at packages/ra-core/src/dataProvider/useUpdateMany.ts:107
mutationMode = 'pessimistic',
getMutateWithMiddlewares,
mutationFn: customMutationFn,
...mutationOptions
} = options;
const dataProviderUpdateMany = useEvent(
(resource: string, params: UpdateManyParams<RecordType>) =>
dataProvider.updateMany<RecordType>(resource, params)
);
const customMutationFnWithDataProviderResult = async (
resource: string | undefined,
params: Omit<UseUpdateManyMutateParams<RecordType>, 'resource'>
) => {
if (resource == null) {
throw new Error('useUpdateMany mutation requires a resource');
}
if (params.ids == null) {
throw new Error('useUpdateMany mutation requires an array of ids');
}
if (!params.data) {
throw new Error(
'useUpdateMany mutation requires a non-empty data object'
);
}
if (customMutationFn == null) {
return dataProviderUpdateMany(
resource,
params as UpdateManyParams<RecordType>
);
}
return {
data: await customMutationFn({ resource, ...params }),
};
};
View on GitHub (pinned to 051f511bb0)
Solutions
- Guard the call: only invoke mutate when Array.isArray(ids) && ids.length > 0.
- Initialize selection state as [] rather than null/undefined.
- Pass the correct key — useUpdateMany expects { ids, data }, not { id, data } (that is useUpdate).
- Check the ids variable is not shadowed or assigned after the mutate call.
Example fix
// before
mutate({ ids: selectedIds, data: { status: 'archived' } }); // selectedIds may be null
// after
if (selectedIds && selectedIds.length > 0) {
mutate({ ids: selectedIds, data: { status: 'archived' } });
} Defensive patterns
Strategy: validation
Validate before calling
const canUpdate = Array.isArray(selectedIds) && selectedIds.length > 0 && data != null;
if (canUpdate) mutate({ ids: selectedIds, data }); Type guard
const hasIds = (p: { ids?: unknown }): p is { ids: unknown[] } =>
Array.isArray(p.ids); Try / catch
try {
mutate({ ids, data });
} catch (e) {
if (e instanceof Error && e.message.includes('requires an array of ids')) {
notify('Select at least one record first', { type: 'warning' });
}
} Prevention
- Initialize ids state as [], never null/undefined.
- Gate mutate behind ids.length > 0.
- Type the payload with UpdateManyParams so ids is required at compile time.
- Unit test the mutate call with an empty selection.
When it happens
Trigger: Calling mutate({ ids: undefined, data }) — e.g. ids derived from a selection state that was never populated, or a variable that is still null when the mutation fires.
Common situations: Bulk-update toolbars on a Datagrid where the selected-ids state starts empty and the mutation runs before the user selects rows; passing the wrong prop (id instead of ids); an async source for ids that resolves after the mutate call.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- useUpdateMany mutation requires a non-empty data object
- useCreate mutation requires a resource
- useCreate mutation requires a non-empty data object
- useDelete mutation requires a resource
- useDelete mutation requires a non-empty id
AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30).
Data as JSON: /api/errors/ee8648e1f572ad6b.
Report an issue: GitHub.