marmelab/react-admin · error · Error

useMutationWithMutationMode mutation requires a mutationFn

Error message

useMutationWithMutationMode mutation requires a mutationFn

What it means

useMutationWithMutationMode is a generic wrapper around react-query's useMutation that handles optimistic/undoable modes. Its options must include a mutationFn describing the actual call; without one there is nothing to execute, so it throws at hook setup time rather than failing later inside react-query.

Source

Thrown at packages/ra-core/src/dataProvider/useMutationWithMutationMode.ts:37

>(
    params: TVariables = {} as TVariables,
    options: UseMutationWithMutationModeOptions<ErrorType, TData, TVariables>
): UseMutationWithMutationModeResult<boolean, ErrorType, TData, TVariables> => {
    const queryClient = useQueryClient();
    const addUndoableMutation = useAddUndoableMutation();
    const {
        mutationKey,
        mutationMode = 'pessimistic',
        mutationFn,
        getMutateWithMiddlewares,
        updateCache,
        getQueryKeys,
        onUndo,
        ...mutationOptions
    } = options;

    if (mutationFn == null) {
        throw new Error(
            'useMutationWithMutationMode mutation requires a mutationFn'
        );
    }

    const mutationFnEvent = useEvent(mutationFn);
    const updateCacheEvent = useEvent(updateCache);
    const getQueryKeysEvent = useEvent(getQueryKeys);
    const getSnapshotEvent = useEvent(
        /**
         * Snapshot the previous values via queryClient.getQueriesData()
         *
         * The snapshotData ref will contain an array of tuples [query key, associated data]
         *
         * @example
         * [
         *   [['posts', 'getList'], { data: [{ id: 1, title: 'Hello' }], total: 1 }],
         *   [['posts', 'getMany'], [{ id: 1, title: 'Hello' }]],
         * ]

View on GitHub (pinned to 051f511bb0)

Solutions

  1. Always pass a mutationFn in options: useMutationWithMutationMode({ mutationFn: args => dataProvider.update(...), ... }).
  2. If the fn is conditional, provide a fallback that rejects, or skip calling the hook.
  3. Check option key spelling is exactly mutationFn.

Example fix

// before
useMutationWithMutationMode({ mutationMode, onUndo });
// after
useMutationWithMutationMode({ mutationMode, onUndo, mutationFn: ({ resource, params }) => dataProvider.update(resource, params) });
Defensive patterns

Strategy: validation

Validate before calling

if (typeof options.mutationFn !== 'function') {
  throw new TypeError('useMutationWithMutationMode: mutationFn is required');
}

Type guard

const hasMutationFn = <T>(o: T & { mutationFn?: unknown }): o is T & { mutationFn: Function } =>
  typeof o.mutationFn === 'function';

Try / catch

// thrown at render time by the hook; guard at the call site instead
if (!hasMutationFn(options)) throw new TypeError('mutationFn missing');
useMutationWithMutationMode(options);

Prevention

When it happens

Trigger: Calling useMutationWithMutationMode({}) or omitting mutationFn in the options object; building options dynamically where mutationFn is conditionally spread; a typo like mutationfunction or fn instead of mutationFn.

Common situations: Abstracting mutation hooks where the mutationFn is expected to be injected but a caller forgot it; refactors that renamed mutationFn; conditional option assembly with spread of possibly-undefined objects.

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