marmelab/react-admin · error · Error
useCanAccess must be used inside a <Resource> component or p
Error message
useCanAccess must be used inside a <Resource> component or provide a resource prop
What it means
useCanAccess performs permission checks against a specific resource, so it needs to know which resource to check. It resolves the resource via useResourceContext, which reads the resource prop or the surrounding <Resource> context. When neither exists, the library throws rather than silently returning a wrong authorization answer.
Source
Thrown at packages/ra-core/src/auth/useCanAccess.ts:60
* return null;
* }
* if (error) {
* return <div>{error.message}</div>;
* }
* return <PostEdit />;
* };
*/
export const useCanAccess = <
RecordType extends Record<string, any> = Record<string, any>,
ErrorType extends Error = Error,
>(
params: UseCanAccessOptions<RecordType, ErrorType>
): UseCanAccessResult<ErrorType> => {
const authProvider = useAuthProvider();
const resource = useResourceContext(params);
if (!resource) {
throw new Error(
'useCanAccess must be used inside a <Resource> component or provide a resource prop'
);
}
const record = useRecordContext<RecordType>(params);
const { record: _record, ...restParams } = params;
const authProviderHasCanAccess = !!authProvider?.canAccess;
const queryResult = useQuery({
queryKey: [
'auth',
'canAccess',
{ ...restParams, recordId: record?.id, resource },
],
queryFn: async ({ signal }) => {
if (!authProvider || !authProvider.canAccess) {
return true;
}
return authProvider.canAccess({View on GitHub (pinned to 051f511bb0)
Solutions
- Pass the resource explicitly: `useCanAccess({ resource: 'posts', action: 'edit', record })`.
- Move the component inside a <Resource name="posts"> tree so useResourceContext resolves the resource.
- In tests/Storybook, wrap the component with `<Resource name="posts">` (inside an <Admin> or test AdminContext) to provide the context.
- Fix custom wrapper components to forward the resource prop instead of dropping it.
Example fix
// before
const { canAccess } = useCanAccess({ action: 'edit', record });
// after
const { canAccess } = useCanAccess({ resource: 'posts', action: 'edit', record }); Defensive patterns
Strategy: validation
Validate before calling
// Verify a resource is available before calling the hook
const resource = useResourceContext();
if (!resource) {
console.warn('useCanAccess requires a resource prop or <Resource> context');
} Type guard
function hasResourceContext(params?: { resource?: string }): params is { resource: string } & typeof params {
return typeof params?.resource === 'string' && params.resource.length > 0;
} Try / catch
// React hooks cannot be wrapped in try/catch for render-time throws;
// guard at the call site instead:
const resource = params.resource ?? useOptionalResourceContext?.();
if (!resource) return null; // or render fallback
const { isPending, canAccess } = useCanAccess({ resource, action: 'edit', record }); Prevention
- Always pass an explicit `resource` prop in reusable components.
- Wrap standalone usages (tests, Storybook, dashboards) in <Resource name="...">.
- Keep permission-gated components inside the Admin/Resource tree.
- Forward the resource prop in custom wrapper hooks instead of dropping it.
When it happens
Trigger: Calling useCanAccess({ action, record }) outside any <Resource> context (e.g. in a standalone page, a layout, or before the router defines the resource) without passing a `resource` prop.
Common situations: Using useCanAccess in a custom dashboard/menu component rendered outside Resource definitions; rendering a permissions-gated component in Storybook or tests without wrapping it in <Resource name="...">; forgetting to spread a resource prop through a custom wrapper.
Related errors
- useCreateController requires a non-empty resource prop or co
- useEditController requires a non-empty resource prop or cont
- useArrayInput must be used inside an ArrayInputContextProvid
- useSimpleFormIterator must be used inside a SimpleFormIterat
- useSimpleFormIteratorItem must be used inside a SimpleFormIt
AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30).
Data as JSON: /api/errors/57b6ae36cfccbdd2.
Report an issue: GitHub.