{"record":{"id":"c452275e15045cb6","repo":"marmelab/react-admin","slug":"useupdate-mutation-requires-a-resource","errorCode":null,"errorMessage":"useUpdate mutation requires a resource","messagePattern":"useUpdate mutation requires a resource","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ra-core/src/dataProvider/useUpdate.ts","lineNumber":108,"sourceCode":"    const dataProvider = useDataProvider();\n    const queryClient = useQueryClient();\n    const {\n        mutationMode = 'pessimistic',\n        getMutateWithMiddlewares,\n        mutationFn: customMutationFn,\n        ...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 }),","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/marmelab/react-admin/blob/051f511bb0afb5ea565c2d3728bf4dab0a6fa5e0/packages/ra-core/src/dataProvider/useUpdate.ts#L90-L126","documentation":"useUpdate wraps dataProvider.update; its mutate function takes the resource as the first argument. A null/undefined resource means the target resource is unknown, so the hook throws before touching the data provider.","triggerScenarios":"Calling mutate(undefined, { id, data }); resource read from an undefined route param or missing context; invoking mutate in a component used outside a Resource.","commonSituations":"Custom edit toolbar reused outside an edit route; resource prop not forwarded to a deeply nested component; dynamic resource from URL that is undefined on the wrong page.","solutions":["Pass the resource string: mutate('posts', { id, data }).","Use useResourceContext() and render only when it is defined.","Add a fallback default resource for shared components."],"exampleFix":"// before\nupdate(resource, { id, data }); // resource undefined\n// after\nconst resource = useResourceContext();\nif (!resource) return;\nupdate(resource, { id, data });","handlingStrategy":"validation","validationCode":"if (typeof resource !== 'string' || resource.length === 0) {\n  throw new TypeError('useUpdate: resource must be a non-empty string');\n}","typeGuard":"const hasResource = (r: unknown): r is string => typeof r === 'string' && r.length > 0;","tryCatchPattern":"try {\n  await mutate(resource!, { id, data });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('requires a resource')) {\n    notify('Update failed: unknown resource', { type: 'warning' });\n  } else throw e;\n}","preventionTips":["Resolve resource with useResourceContext() before mutating.","Pass resource as an explicit prop to shared edit components.","Check route params resolve before rendering mutation triggers."],"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"}