{"record":{"id":"54ce84bac236819c","repo":"marmelab/react-admin","slug":"usedeletemany-mutation-requires-a-resource","errorCode":null,"errorMessage":"useDeleteMany mutation requires a resource","messagePattern":"useDeleteMany mutation requires a resource","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ra-core/src/dataProvider/useDeleteMany.ts","lineNumber":104,"sourceCode":">(\n    resource?: string,\n    params: Partial<DeleteManyParams<RecordType>> = {},\n    options: UseDeleteManyOptions<RecordType, MutationError> = {}\n): UseDeleteManyResult<RecordType, MutationError> => {\n    const dataProvider = useDataProvider();\n    const queryClient = useQueryClient();\n    const {\n        mutationMode = 'pessimistic',\n        mutationFn: customMutationFn,\n        onSettled,\n        ...mutationOptions\n    } = options;\n    const customMutationFnWithDataProviderResult = async (\n        resource: string | undefined,\n        params: Omit<UseDeleteManyMutateParams<RecordType>, 'resource'>\n    ) => {\n        if (resource == null) {\n            throw new Error('useDeleteMany mutation requires a resource');\n        }\n        if (params.ids == null) {\n            throw new Error('useDeleteMany mutation requires an array of ids');\n        }\n        if (customMutationFn == null) {\n            return dataProvider.deleteMany<RecordType>(\n                resource,\n                params as DeleteManyParams<RecordType>\n            );\n        }\n\n        return {\n            data: await customMutationFn({ resource, ...params }),\n        };\n    };\n\n    const [mutate, mutationResult] = useMutationWithMutationMode<\n        MutationError,","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/marmelab/react-admin/blob/051f511bb0afb5ea565c2d3728bf4dab0a6fa5e0/packages/ra-core/src/dataProvider/useDeleteMany.ts#L86-L122","documentation":"useDeleteMany wraps dataProvider.deleteMany in a react-query mutation. The mutate function accepts the resource as its first argument; if it is null or undefined, react-admin cannot know which resource to delete records from, so it throws immediately instead of calling the data provider. This is a programming-error guard against calling mutate() without a resource.","triggerScenarios":"Calling mutate(undefined, { ids: [...] }) or mutate(null, {...}); passing a resource variable that is undefined because it came from an unmatched route param or an uninitialized prop; destructuring useDeleteMany and invoking mutate before the resource prop is set.","commonSituations":"Dynamic resource names read from useParams() that are undefined outside the resource route; a custom list toolbar component reused outside a Resource context; refactoring that moved the mutate call to a place where the resource string is no longer in scope.","solutions":["Pass the resource string as the first argument to mutate: mutate('posts', { ids }).","If the resource comes from useResourceContext() or route params, render the component only inside the resource route or provide a default.","Guard with an early check: if (!resource) return; before calling mutate."],"exampleFix":"// before\nconst [deleteMany] = useDeleteMany();\ndeleteMany(resource, { ids }); // resource may be undefined\n// after\nconst resource = useResourceContext();\nconst [deleteMany] = useDeleteMany();\nif (resource) deleteMany(resource, { ids });","handlingStrategy":"validation","validationCode":"if (typeof resource !== 'string' || resource.length === 0) {\n  throw new TypeError('useDeleteMany: 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!, { ids });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('requires a resource')) {\n    notify('Cannot delete: no resource selected', { type: 'warning' });\n  } else throw e;\n}","preventionTips":["Always source resource via useResourceContext() or an explicit prop.","Render mutation-triggering components only inside a Resource route.","Add a runtime check on resource in shared toolbar components."],"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"}