marmelab/react-admin · error · Error

useUpdate mutation requires a non-empty id

Error message

useUpdate mutation requires a non-empty id

What it means

useUpdate's mutate requires a non-null id of the record to update. When params.id is null or undefined the target record is unknown, so the hook throws before calling dataProvider.update.

Solutions

  1. Pass the record id: mutate('posts', { id: record.id, data }).
  2. Disable save actions while the record query is loading.
  3. Verify the data provider returns an id field for every record.

Example fix

// before
update('posts', { id: record?.id, data }); // may be undefined
// after
if (record?.id != null) update('posts', { id: record.id, data });
Defensive patterns

Strategy: validation

Validate before calling

if (id == null) {
  throw new TypeError('useUpdate: id must be provided');
}

Type guard

const hasId = (p: { id?: unknown }): p is { id: string | number } =>
  p.id != null;

Try / catch

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

Prevention

When it happens

Trigger: Calling mutate('posts', { id: undefined, data }); the record loaded asynchronously so record.id is undefined at call time; passing a record object instead of its id.

Common situations: Save button clicked before the record query resolves; forms using getValues() on an empty form; passing the whole record ({ ...record }) where id is missing due to a misconfigured provider that omits the id field.

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

Appendix: source

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

        mutationMode = 'pessimistic',
        getMutateWithMiddlewares,
        mutationFn: customMutationFn,
        ...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 }),
        };
    };

View on GitHub (pinned to 051f511bb0)