marmelab/react-admin · error · Error

useDelete mutation requires a non-empty id

Error message

useDelete mutation requires a non-empty id

What it means

useDelete validates that params.id is non-null before deleting, since a delete call without a record id is invalid. The check occurs before the data provider is contacted.

Source

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

    options: UseDeleteOptions<RecordType, MutationError> = {}
): UseDeleteResult<RecordType, MutationError> => {
    const dataProvider = useDataProvider();
    const queryClient = useQueryClient();
    const {
        mutationMode = 'pessimistic',
        mutationFn: customMutationFn,
        onSettled,
        ...mutationOptions
    } = options;
    const customMutationFnWithDataProviderResult = async (
        resource: string | undefined,
        params: Omit<UseDeleteMutateParams<RecordType>, 'resource'>
    ) => {
        if (resource == null) {
            throw new Error('useDelete mutation requires a resource');
        }
        if (params.id == null) {
            throw new Error('useDelete mutation requires a non-empty id');
        }
        if (customMutationFn == null) {
            return dataProvider.delete<RecordType>(
                resource,
                params as DeleteParams<RecordType>
            );
        }

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

    const [mutate, mutationResult] = useMutationWithMutationMode<
        MutationError,
        DeleteResult<RecordType>,
        UseDeleteMutateParams<RecordType>
    >(

View on GitHub (pinned to 051f511bb0)

Solutions

  1. Always pass an id: mutate('posts', { id: record.id })
  2. Disable/guard the delete button until the record is loaded
  3. Validate id != null before invoking the mutation

Example fix

// before
mutate('posts', { id: record?.id });
// after
if (record?.id != null) mutate('posts', { id: record.id });
Defensive patterns

Strategy: validation

Validate before calling

if (id == null) {
  throw new Error('Cannot delete: record id is missing');
}
mutate('posts', { id });

Type guard

const hasId = (p: { id?: Identifier | null }): p is { id: Identifier } =>
  p.id !== undefined && p.id !== null;

Try / catch

try {
  await mutate('posts', { id });
} catch (e) {
  if (/requires a non-empty id/.test(e.message)) {
    notify('No record selected to delete', { type: 'warning' });
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling mutate(resource, {}) without id, or mutating while the record is still loading so record.id is undefined.

Common situations: Delete buttons rendered before useGetOne resolves; list selection rows where the selected id was never stored in state.

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/9988ae316d0e04c8. Report an issue: GitHub.