marmelab/react-admin · error · Error

useUpdate mutation requires a non-empty data object

Error message

useUpdate mutation requires a non-empty data object

What it means

useUpdate requires a non-empty data object containing the fields to change. A falsy params.data (undefined, null, or empty object) gives the provider nothing to write, so the hook throws before calling dataProvider.update.

Source

Thrown at packages/ra-core/src/dataProvider/useUpdate.ts:114

        ...mutationOptions
    } = options;

    const dataProviderUpdate = useEvent(
        (resource: string, params: UpdateParams<RecordType>) =>
            dataProvider.update<RecordType>(resource, params)
    );
    const customMutationFnWithDataProviderResult = async (
        resource: string | undefined,
        params: Omit<UseUpdateMutateParams<RecordType>, 'resource'>
    ) => {
        if (resource == null) {
            throw new Error('useUpdate mutation requires a resource');
        }
        if (params.id == null) {
            throw new Error('useUpdate mutation requires a non-empty id');
        }
        if (!params.data) {
            throw new Error(
                'useUpdate mutation requires a non-empty data object'
            );
        }
        if (customMutationFn == null) {
            return dataProviderUpdate(
                resource,
                params as UpdateParams<RecordType>
            );
        }

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

    const [mutate, mutationResult] = useMutationWithMutationMode<
        ErrorType,
        UpdateResult<RecordType>,

View on GitHub (pinned to 051f511bb0)

Solutions

  1. Pass a populated payload: mutate('posts', { id, data: { title } }).
  2. Check Object.keys(data).length > 0 before calling mutate and skip the call otherwise.
  3. Verify form values are mapped into params.data, not another key.

Example fix

// before
update('posts', { id, data: values }); // values may be {}
// after
if (values && Object.keys(values).length > 0) update('posts', { id, data: values });
Defensive patterns

Strategy: validation

Validate before calling

if (!data || Object.keys(data).length === 0) {
  throw new TypeError('useUpdate: data must be a non-empty object');
}

Type guard

const hasData = (p: { data?: unknown }): p is { data: Record<string, unknown> } =>
  typeof p.data === 'object' && p.data !== null && Object.keys(p.data).length > 0;

Try / catch

try {
  await mutate(resource, { id, data });
} catch (e) {
  if (e instanceof Error && e.message.includes('non-empty data')) {
    notify('No changes to save', { type: 'info' });
  } else throw e;
}

Prevention

When it happens

Trigger: Calling mutate('posts', { id: 1 }) with no data; passing an object that is empty because form values were never populated; spreading a form values object that ends up {}.

Common situations: Autosave logic firing with an empty diff; form library returning an empty object on untouched forms; refactors that renamed the data key so the actual payload lands under a different property.

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