marmelab/react-admin · error
<DeleteButton> components should be used inside a <Resource>
Error message
<DeleteButton> components should be used inside a <Resource> component or provided the resource prop.
What it means
DeleteButton deletes the current record of a resource; it needs both a record (from RecordContext or props) and a resource name (from ResourceContext or props). When the resource cannot be resolved, the delete mutation and access-control check cannot be built, so it throws.
Source
Thrown at packages/ra-ui-materialui/src/button/DeleteButton.tsx:70
* return <Edit actions={<EditActions />} {...props} />;
* };
*/
export const DeleteButton = React.forwardRef(function DeleteButton<
RecordType extends RaRecord = any,
>(
inProps: DeleteButtonProps<RecordType>,
ref: React.ForwardedRef<HTMLButtonElement>
) {
const props = useThemeProps({
name: PREFIX,
props: inProps,
});
const { mutationMode, ...rest } = props;
const record = useRecordContext(props);
const resource = useResourceContext(props);
if (!resource) {
throw new Error(
'<DeleteButton> components should be used inside a <Resource> component or provided the resource prop.'
);
}
const { canAccess, isPending } = useCanAccess({
action: 'delete',
resource,
record,
});
const saveContext = useSaveContext(props);
if (!record || record.id == null || !canAccess || isPending) {
return null;
}
const finalMutationMode = mutationMode
? mutationMode
: saveContext?.mutationMode
? saveContext.mutationMode
: 'undoable';View on GitHub (pinned to 051f511bb0)
Solutions
- Pass resource (and record if no context): <DeleteButton resource="posts" record={post} />
- Wrap in <ResourceContextProvider> / <RecordContextProvider> or render inside Edit/Show/List views
- Forward resource from parent components when abstracting the button
Example fix
// before
export const MyActions = () => <DeleteButton />;
// after
export const MyActions = ({ resource, record }) => (
<DeleteButton resource={resource} record={record} />
); Defensive patterns
Strategy: type-guard
Validate before calling
if (!resource || !record) return null; // DeleteButton needs both
Type guard
const canDelete = (p: { resource?: string; record?: Record }): p is { resource: string; record: Record } =>
typeof p.resource === 'string' && p.resource.length > 0 && p.record != null; Try / catch
try {
return <DeleteButton {...props} />;
} catch (e) {
if (e.message.includes('DeleteButton')) {
return <DeleteButton resource={fallbackResource} record={fallbackRecord} {...props} />;
}
throw e;
} Prevention
- Keep DeleteButton inside Edit/Show/List or record-context scope
- Pass resource and record explicitly in extracted/shared components
- Wrap custom rows with RecordContextProvider + ResourceContextProvider
- Add tests for shared action components rendered outside standard views
When it happens
Trigger: Rendering <DeleteButton /> outside a record/list context without resource (and typically record) props; using it in a custom row renderer that dropped the resource context; mounting it app-level for 'delete current item' logic.
Common situations: Custom action toolbars outside Edit/Show/List views; refactors moving DeleteButton into shared components; test setups rendering the button alone.
Related errors
- <BulkDeleteButton> components should be used inside a <Resou
- <CreateButton> components should be used inside a <Resource>
- <DeleteWithConfirmButton> components should be used inside a
- <DeleteWithUndoButton> components should be used inside a <R
- <EditButton> components should be used inside a <Resource> c
AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30).
Data as JSON: /api/errors/565eea92226dc450.
Report an issue: GitHub.