marmelab/react-admin · error · Error

useDeleteMany mutation requires an array of ids

Error message

useDeleteMany mutation requires an array of ids

What it means

useDeleteMany's mutate requires an ids array identifying which records to delete. When params.ids is null or undefined, the library cannot build a deleteMany call and throws. This guards against malformed mutation arguments reaching the data provider.

Source

Thrown at packages/ra-core/src/dataProvider/useDeleteMany.ts:107

    options: UseDeleteManyOptions<RecordType, MutationError> = {}
): UseDeleteManyResult<RecordType, MutationError> => {
    const dataProvider = useDataProvider();
    const queryClient = useQueryClient();
    const {
        mutationMode = 'pessimistic',
        mutationFn: customMutationFn,
        onSettled,
        ...mutationOptions
    } = options;
    const customMutationFnWithDataProviderResult = async (
        resource: string | undefined,
        params: Omit<UseDeleteManyMutateParams<RecordType>, 'resource'>
    ) => {
        if (resource == null) {
            throw new Error('useDeleteMany mutation requires a resource');
        }
        if (params.ids == null) {
            throw new Error('useDeleteMany mutation requires an array of ids');
        }
        if (customMutationFn == null) {
            return dataProvider.deleteMany<RecordType>(
                resource,
                params as DeleteManyParams<RecordType>
            );
        }

        return {
            data: await customMutationFn({ resource, ...params }),
        };
    };

    const [mutate, mutationResult] = useMutationWithMutationMode<
        MutationError,
        DeleteManyResult<RecordType>,
        UseDeleteManyMutateParams<RecordType>
    >(

View on GitHub (pinned to 051f511bb0)

Solutions

  1. Always pass an array: mutate('posts', { ids: selectedIds }).
  2. Default selection state to [] instead of undefined.
  3. Disable the delete action until ids is a non-empty array.

Example fix

// before
deleteMany('posts', { ids: selectedIds }); // selectedIds?: Identifier[]
// after
deleteMany('posts', { ids: selectedIds ?? [] });
Defensive patterns

Strategy: validation

Validate before calling

if (!Array.isArray(ids) || ids.length === 0) {
  throw new TypeError('useDeleteMany: ids must be a non-empty array');
}

Type guard

const hasIds = (v: unknown): v is Array<string | number> => Array.isArray(v) && v.length > 0;

Try / catch

try {
  await mutate(resource, { ids });
} catch (e) {
  if (e instanceof Error && e.message.includes('array of ids')) {
    notify('Select at least one record first', { type: 'warning' });
  } else throw e;
}

Prevention

When it happens

Trigger: Calling mutate('posts', {}) or mutate('posts', { ids: undefined }); passing ids from a selection state that was never initialized (e.g. selectedIds from an empty/unmounted data table); TypeScript disabled so the Omit<UseDeleteManyMutateParams> shape is not enforced.

Common situations: Bulk-delete buttons clicked before row selection state loads; storing selectedIds in a store that resets to undefined; hand-rolled calls that pass ids as a non-array like a single id.

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


AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30). Data as JSON: /api/errors/1a3cdddebf97ca4f. Report an issue: GitHub.