{"record":{"id":"1f8dba4a794e95ad","repo":"marmelab/react-admin","slug":"useupdate-mutation-requires-a-non-empty-data-objec","errorCode":null,"errorMessage":"useUpdate mutation requires a non-empty data object","messagePattern":"useUpdate mutation requires a non-empty data object","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ra-core/src/dataProvider/useUpdate.ts","lineNumber":114,"sourceCode":"        ...mutationOptions\n    } = options;\n\n    const dataProviderUpdate = useEvent(\n        (resource: string, params: UpdateParams<RecordType>) =>\n            dataProvider.update<RecordType>(resource, params)\n    );\n    const customMutationFnWithDataProviderResult = async (\n        resource: string | undefined,\n        params: Omit<UseUpdateMutateParams<RecordType>, 'resource'>\n    ) => {\n        if (resource == null) {\n            throw new Error('useUpdate mutation requires a resource');\n        }\n        if (params.id == null) {\n            throw new Error('useUpdate mutation requires a non-empty id');\n        }\n        if (!params.data) {\n            throw new Error(\n                'useUpdate mutation requires a non-empty data object'\n            );\n        }\n        if (customMutationFn == null) {\n            return dataProviderUpdate(\n                resource,\n                params as UpdateParams<RecordType>\n            );\n        }\n\n        return {\n            data: await customMutationFn({ resource, ...params }),\n        };\n    };\n\n    const [mutate, mutationResult] = useMutationWithMutationMode<\n        ErrorType,\n        UpdateResult<RecordType>,","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/marmelab/react-admin/blob/051f511bb0afb5ea565c2d3728bf4dab0a6fa5e0/packages/ra-core/src/dataProvider/useUpdate.ts#L96-L132","documentation":"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.","triggerScenarios":"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 {}.","commonSituations":"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.","solutions":["Pass a populated payload: mutate('posts', { id, data: { title } }).","Check Object.keys(data).length > 0 before calling mutate and skip the call otherwise.","Verify form values are mapped into params.data, not another key."],"exampleFix":"// before\nupdate('posts', { id, data: values }); // values may be {}\n// after\nif (values && Object.keys(values).length > 0) update('posts', { id, data: values });","handlingStrategy":"validation","validationCode":"if (!data || Object.keys(data).length === 0) {\n  throw new TypeError('useUpdate: data must be a non-empty object');\n}","typeGuard":"const hasData = (p: { data?: unknown }): p is { data: Record<string, unknown> } =>\n  typeof p.data === 'object' && p.data !== null && Object.keys(p.data).length > 0;","tryCatchPattern":"try {\n  await mutate(resource, { id, data });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('non-empty data')) {\n    notify('No changes to save', { type: 'info' });\n  } else throw e;\n}","preventionTips":["Skip the mutation when the form diff is empty (common with autosave).","Map form values into params.data explicitly.","Type the mutate params so a missing data key fails at compile time."],"tags":["react-admin","mutation","missing-argument","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"051f511bb0afb5ea565c2d3728bf4dab0a6fa5e0","analyzedAt":"2026-08-30T02:28:14.926Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}