marmelab/react-admin · warning
The returnPromise parameter can only be used if the mutation
Error message
The returnPromise parameter can only be used if the mutationMode is set to pessimistic
What it means
In useMutationWithMutationMode, returning a promise only makes sense in pessimistic mutation mode, where the hook waits for the dataProvider call to finish. In undoable or optimistic modes the mutation resolves before the server call completes, so a returned promise would be meaningless; the hook warns when returnPromise is set with a non-pessimistic mode.
Source
Thrown at packages/ra-core/src/dataProvider/useMutationWithMutationMode.ts:264
}
);
} else {
mutateWithMiddlewares.current = mutationFnEvent;
}
// We need to keep the onSuccess callback here and not in the useMutation for undoable mutations
hasCallTimeOnSuccess.current = !!onSuccess;
// We need to store the onError and onSettled callbacks here to be able to call them in the useMutation hook
// so that they are called even when the calling component is unmounted
callTimeOnError.current = onError;
callTimeOnSettled.current = onSettled;
if (mutationMode) {
mode.current = mutationMode;
}
if (returnPromise && mode.current !== 'pessimistic') {
console.warn(
'The returnPromise parameter can only be used if the mutationMode is set to pessimistic'
);
}
snapshot.current = getSnapshotEvent(
getQueryKeysEvent(
{ ...paramsRef.current, ...callTimeParams },
{
mutationMode: mode.current,
}
)
);
if (mode.current === 'pessimistic') {
if (returnPromise) {
return mutation.mutateAsync(
{ ...paramsRef.current, ...callTimeParams },
// We don't pass onError and onSettled here as we will call them in the useMutation hook side effectsView on GitHub (pinned to 051f511bb0)
Solutions
- Pass mutationMode: 'pessimistic' to the hook (or the mutate call) when using returnPromise: true.
- Remove returnPromise and use onSuccess/onError callbacks if you want undoable/optimistic behavior.
- If mode is configurable, guard: only set returnPromise when the resolved mode is pessimistic.
Example fix
// before
const { mutate } = useCreate();
await mutate('posts', { data }, { returnPromise: true });
// after
const { mutate } = useCreate();
await mutate('posts', { data }, { returnPromise: true, mutationMode: 'pessimistic' }); Defensive patterns
Strategy: validation
Validate before calling
const canReturnPromise = (mutationMode ?? 'undoable') === 'pessimistic';
if (needAwait && !canReturnPromise) throw new Error('Set mutationMode: "pessimistic" to use returnPromise'); Type guard
const isPessimistic = (m) => m === 'pessimistic';
const opts = { returnPromise: true, mutationMode: 'pessimistic' };
if (opts.returnPromise && !isPessimistic(opts.mutationMode)) { /* fix before calling mutate */ } Try / catch
try {
await mutate('posts', { data }, { returnPromise: true, mutationMode: 'pessimistic' });
} catch (error) {
notify(error.message, { type: 'error' });
} Prevention
- Pair returnPromise: true with mutationMode: 'pessimistic' in the same options object.
- Prefer onSuccess/onError callbacks in optimistic/undoable flows.
- Centralize mutation options in a helper that enforces this invariant.
When it happens
Trigger: Calling mutate(..., { returnPromise: true }) while mutationMode is 'undoable' or 'optimistic' (the default), either via options or an inline mutationMode override.
Common situations: Awaiting mutate() for form submission success handling but forgetting to set mutationMode: 'pessimistic'; copying examples that use returnPromise without the matching mode.
Related errors
- The dataProvider threw an error. It should return a rejected
- useCanAccess must be used inside a <Resource> component or p
- useCreateController requires a non-empty resource prop or co
- useEditController requires a non-empty resource prop or cont
- useEditController requires an id prop or a route with an /:i
AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30).
Data as JSON: /api/errors/01b7d4286979cc66.
Report an issue: GitHub.