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

  1. Pass the resource explicitly: `useCanAccess({ resource: 'posts', action: 'edit', record })`.
  2. Move the component inside a <Resource name="posts"> tree so useResourceContext resolves the resource.
  3. In tests/Storybook, wrap the component with `<Resource name="posts">` (inside an <Admin> or test AdminContext) to provide the context.
  4. 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

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


AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30). Data as JSON: /api/errors/57b6ae36cfccbdd2. Report an issue: GitHub.